﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Configuration;
using System.Threading;
using System.Reflection;
using System.Diagnostics;
using System.IO;
//SMO namespaces
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Smo = Microsoft.SqlServer.Management.Smo;
using System.Xml.Linq;


namespace Rhsoft.SqlServer.MetadataManager
{
    public partial class Mainform : Form
    {
        #region Constants
        //Constants to label treenode metadata.
        const string NODETYPE_DB = "DB";
        const string NODETYPE_TABLE = "TBL";
        const string NODETYPE_COLUMN = "COL";
        const string NODETYPE_FK = "FK";
        const string NODETYPE_PROP = "PROP";
        const string NODETYPE_XPROP = "XPROP";
        const string NODETYPE_IX = "IX";
        //ORM Extended properties names
        const string ORM_CONNECTIONSTRING = "ORM_ConnectionStringName";
        const string ORM_CONTEXT_IMPORTS = "ORM_ContextImports";
        const string ORM_CONTEXT_NAME = "ORM_ContextName";
        const string ORM_CONTEXT_NAMESPACE = "ORM_ContextNamespace";
        const string ORM_ENTITY_IMPORTS = "ORM_EntityImports";
        const string ORM_ENTITY_NAMESPACE = "ORM_EntityNamespace";
        const string ORM_GENERATE_MULTIPLE_FILES = "ORM_GenerateMultipleClasses";
        const string ORM_INCLUDE_PREVENT_DEBUG = "ORM_IncludePreventingDebug";
        const string ORM_IS_SEALED = "ORM_IsSealed";
        const string ORM_IS_SERIALIZABLE = "ORM_IsSerializable";
        const string ORM_INCLUDE_CRUD_FUNCTIONS = "ORM_IncludeCRUDFunctions";
        const string ORM_OVERRIDE_CRUD_OPERATIONS = "ORM_OverrideCRUDOperations";
        const string ORM_ONLY_SELECTED = "ORM_OnlySelectedTables";
        const string ORM_SAVEPATH = "ORM_SavePath";
        //ORM Extended properties at table scope.
        const string ORM_CRUD_DELETE = "ORM_Crud_DeleteFunction";
        const string ORM_CRUD_INSERT = "ORM_Crud_InsertFunction";
        const string ORM_CRUD_UPDATE = "ORM_Crud_UpdateFunction";
        const string ORM_ENTITY_NAME = "ORM_EntityName";
        const string ORM_ENTITY_PLURALNAME = "ORM_EntityPluralName"; 
        const string ORM_ENTITY_IS_SEALED = "ORM_IsSealed";
        const string ORM_ENTITY_IS_SERIALIZED = "ORM_IsSerialized";
        #endregion

        #region Fields
        SqlConnection _conn; //Ado.NET Sql Connection.
        Server _serverObject; //Sql Server smo server object.
        ServerConnection _serverConn; //Smo server connection.
        Database _currentDatabase; //Store de current database  object.
        Table _currentTable; //Store the current table object.
        Column _currentColumn; //Store the current column object.
        SqlSmoObject _currentObject; //Store a generic server object.
        string _currentObjectType = null;
        Smo.ExtendedPropertyCollection _currentPropertiesCollection = null;
        bool _serverConnected = false; //Current server state.
        string _currentServerConnectionString = null;
        //DbProperties fields.
        string _propertyOldName = null;
        #endregion

        #region Assembly Attribute Accessors
        public string AssemblyTitle
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly( ).GetCustomAttributes( typeof( AssemblyTitleAttribute ), false );
                if( attributes.Length > 0 )
                {
                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
                    if( titleAttribute.Title != "" )
                    {
                        return titleAttribute.Title;
                    }
                }
                return System.IO.Path.GetFileNameWithoutExtension( Assembly.GetExecutingAssembly( ).CodeBase );
            }
        }
        public string AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly( ).GetName( ).Version.ToString( );
            }
        }
        public string AssemblyDescription
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly( ).GetCustomAttributes( typeof( AssemblyDescriptionAttribute ), false );
                if( attributes.Length == 0 )
                {
                    return "";
                }
                return ( (AssemblyDescriptionAttribute)attributes[0] ).Description;
            }
        }
        public string AssemblyProduct
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly( ).GetCustomAttributes( typeof( AssemblyProductAttribute ), false );
                if( attributes.Length == 0 )
                {
                    return "";
                }
                return ( (AssemblyProductAttribute)attributes[0] ).Product;
            }
        }
        public string AssemblyCopyright
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly( ).GetCustomAttributes( typeof( AssemblyCopyrightAttribute ), false );
                if( attributes.Length == 0 )
                {
                    return "";
                }
                return ( (AssemblyCopyrightAttribute)attributes[0] ).Copyright;
            }
        }
        public string AssemblyCompany
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly( ).GetCustomAttributes( typeof( AssemblyCompanyAttribute ), false );
                if( attributes.Length == 0 )
                {
                    return "";
                }
                return ( (AssemblyCompanyAttribute)attributes[0] ).Company;
            }
        }
        #endregion

        #region Main
        public Mainform( )
        {
            
            InitializeComponent( );
            this.Text = string.Format( "{0} v{1}", AssemblyTitle, AssemblyVersion );
            LoadConfiguration( );
            DisableDatabaseControls( );
            PopulateServers( );
        }
        /// <summary>
        /// Load configuration values.
        /// </summary>
        private void LoadConfiguration( )
        {
            //ConfigValues.DescriptionLabel = ConfigurationManager.AppSettings["DescriptionLabel"].ToString( );
            //ConfigValues.SaveOnLostFocus = Convert.ToBoolean( ConfigurationManager.AppSettings["SaveOnLostFocus"] );
            ConfigValues.DescriptionLabel = Properties.Settings.Default.DescriptionPropertyName;
            ConfigValues.SaveOnLostFocus = Properties.Settings.Default.SaveOnLostFocus;
            ConfigValues.ViewSystemDatabases = Properties.Settings.Default.IncludeSystemDatabases;
            ConfigValues.ViewSystemTables = Properties.Settings.Default.IncludeSystemTables;
            ConfigValues.OverrideProperties = Properties.Settings.Default.OverrideProperties;
            
        }
        
        #endregion

        #region Helpers
        private string ParseValue( string value )
        {
            string ParsedValue = value;
            //Parse variables.
            if(_currentTable !=null)
                ParsedValue = ParseTableName( value, _currentTable.Name );
            if(_currentColumn != null)
                ParsedValue = ParseColumnName( value, _currentColumn.Name );
            return ParsedValue;
        }
        private string ParseTableName( string value, string maskValue  )
        {
            string ParsedValue=string.Empty;
            //Parse variables.
            ParsedValue = value.Replace( "$TableName$", maskValue );
            return ParsedValue;
        }
        private string ParseDatabaseName( string value, string maskValue )
        {
            string ParsedValue = string.Empty;
            //Parse variables.
            ParsedValue = value.Replace( "$DatabaseName$", maskValue );
            return ParsedValue;
        }
        private string ParseColumnName( string value, string maskValue )
        {
            string ParsedValue = string.Empty;
            //Parse variables.
            ParsedValue = value.Replace( "$ColumnName$", maskValue );
            return ParsedValue;
        }
        private void ShowinfoMessage( string message )
        {
            MessageBox.Show( message, "Information message", MessageBoxButtons.OK, MessageBoxIcon.Information );
        }
        private DialogResult ShowConfirmationMessage( string message )
        {
            return MessageBox.Show( message, "Dialog confirmation", MessageBoxButtons.OKCancel, MessageBoxIcon.Question );
        }
        private void ShowAlertMessage( string message )
        {
            MessageBox.Show( message, "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
        }
        private void ShowErrorMessage( string message )
        {
            MessageBox.Show( message, "Error notification", MessageBoxButtons.OK, MessageBoxIcon.Error );
        }
        private void ShowWaitDialog( string message )
        {
            
        }
        #endregion

        #region User interface
        private void EnableDatabaseControls( )
        {
            DbTree.Enabled = true;
            DbList.Enabled = true;
            FieldDescription.Enabled = true;
            DbProperties.Enabled = true;
            bSaveDescription.Enabled = true;
            bAddProperty.Enabled = true;
        }
        private void DisableDatabaseControls( )
        {
            DbTree.Enabled = false;
            DbList.Enabled = false;
            FieldDescription.Enabled = false;
            DbProperties.Enabled = false;
            bSaveDescription.Enabled = false;
            bAddProperty.Enabled = false;
        }
        private void ClearDatabaseControls( )
        {
            DbTree.Nodes.Clear( );
            DbList.Items.Clear( ); DbList.Refresh( );
            DbProperties.Rows.Clear( );
            FieldDescription.Text = "";
        }
        private void EnableMenuItems( )
        {
        }
        private void DisableMenuItems( )
        {

        }
        #endregion

        #region Extended properties management
        /// <summary>
        /// Take current properties collection and fill the properties listview.
        /// </summary>
        /// <param name="propCol"></param>
        private void PopulateExtendedProperties( Smo.ExtendedPropertyCollection propCol )
        {
            try
            {
                //Set the current properties collection object which is used to add or remove properties.
                _currentPropertiesCollection = propCol;
                //Populate extended properties view.
                DbProperties.Rows.Clear( );
                foreach( ExtendedProperty item in propCol )
                {
                    //Omit the property to store description and avoid delete or editing name.
                    if( !( item.Name == ConfigValues.DescriptionLabel ) )
                        DbProperties.Rows.Add( item.Name, item.Value.ToString( ) );
                }
                //Fill de description field.
                if( _currentPropertiesCollection[ConfigValues.DescriptionLabel] != null )
                {
                    //Show in text field to edit.
                    FieldDescription.Text = _currentPropertiesCollection[ConfigValues.DescriptionLabel].Value.ToString( );
                }
                
            }
            catch( InvalidOperationException ex ) { }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        /// <summary>
        /// Update property value. Support variables:
        /// $TableName$, $ColumnName$ to custom values with tables or column names
        /// </summary>
        /// <param name="extendedPropertyName"></param>
        /// <param name="value"></param>
        private void SetExtendedProperty( string extendedPropertyName, string value )
        {
            //
            Smo.ExtendedPropertyCollection PropCol = _currentTable.ExtendedProperties;
            string ParsedValue = value;
            //Parse variables.
            ParsedValue = ParsedValue.Replace( "$TableName$", _currentTable.Name );
            ParsedValue = ParsedValue.Replace( "$ColumnName$", _currentColumn.Name );
            PropCol[extendedPropertyName].Value = ParsedValue;
            _currentTable.Alter( );
        }
        private void RemoveProperty( SqlSmoObject smoObject, string objectType, string name )
        {
            try
            {
                //Delete the property.            
                _currentPropertiesCollection[name].Drop();
                //Repopulate the list view control with the current properties collection.
                PopulateExtendedProperties( _currentPropertiesCollection );
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void AddSingleExtendedProperty( SqlSmoObject smoObject, string objectType )
        {
            //
            Smo.ExtendedPropertyCollection PropertiesCol = null;
            try
            {
                switch( objectType )
                {
                    case NODETYPE_DB:
                        Database Db = (Database)smoObject;
                        PropertiesCol = Db.ExtendedProperties;
                        PropertiesCol.Add( new ExtendedProperty( smoObject, string.Format( "NewProperty{0}", PropertiesCol.Count + 1 ), "DefaultValue" ) );
                        Db.Alter( );
                        break;
                    case NODETYPE_TABLE:
                        Table t = (Table)smoObject;
                        PropertiesCol = t.ExtendedProperties;
                        PropertiesCol.Add( new ExtendedProperty( smoObject, string.Format("NewProperty{0}", PropertiesCol.Count + 1), "DefaultValue" ) );
                        t.Alter( );
                        break;
                    case NODETYPE_COLUMN:
                        Column c = (Column)smoObject;
                        PropertiesCol = c.ExtendedProperties;
                        PropertiesCol.Add( new ExtendedProperty( smoObject, string.Format("NewProperty{0}", PropertiesCol.Count + 1), "DefaultValue" )  ) ;
                        c.Alter( );
                        break;
                    default:
                        break;
                }
                PopulateExtendedProperties( PropertiesCol );
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void AddExtendedProperty( SqlSmoObject smoObject, string objectType, string name, string value )
        {
            //
            Smo.ExtendedPropertyCollection PropertiesCol = null;
            try
            {
                switch( objectType )
                {
                    case NODETYPE_DB:
                        Database db = (Database)smoObject;
                        PropertiesCol = db.ExtendedProperties;
                        if( PropertiesCol[name] != null )
                        {
                            //Drop first to override.
                            if( Properties.Settings.Default.OverrideProperties )
                            {
                                PropertiesCol[name].Drop( );
                                db.Alter( );
                                PropertiesCol.Add( new ExtendedProperty( db, name, ParseDatabaseName( value, db.Name ) ) );
                                db.Alter( );
                            }
                        }
                        else
                        {
                            PropertiesCol.Add( new ExtendedProperty( db, name, ParseDatabaseName( value, db.Name ) ) );
                            db.Alter( );
                        }
                        //Refresh current properties view.
                        PropertiesCol = db.ExtendedProperties;
                        PopulateExtendedProperties( PropertiesCol );
                        break;
                    case NODETYPE_TABLE:
                        Table t = (Table)smoObject;             
                        PropertiesCol = t.ExtendedProperties;
                        if( PropertiesCol[name] != null )
                        {
                            //Drop first to override.
                            if( Properties.Settings.Default.OverrideProperties  )
                            {
                                PropertiesCol[name].Drop( );
                                t.Alter( );
                                PropertiesCol.Add( new ExtendedProperty( t, name, ParseTableName( value, t.Name ) ) );
                                t.Alter( );
                            }
                        }
                        else
                        {
                            PropertiesCol.Add( new ExtendedProperty( t, name, ParseTableName( value, t.Name ) ) );
                            t.Alter( );
                        }
                        //Refresh current properties view.
                        PropertiesCol = t.ExtendedProperties;
                        PopulateExtendedProperties( PropertiesCol );
                        break;
                    default:
                        break;
                }
                
            }
            catch( Exception ex ) { ShowErrorMessage( ex.Message ); }
            finally { ProgressBar.Visible = false; }
        }
        private void AddExtendedPropertyAtScope( string objectType, string name, string value, Scope scope )
        {
            //If the scope is set to database scope.
            if( scope == Scope.DatabaseScope )
            {
                foreach( Table table in _currentDatabase.Tables )
                {
                    AddExtendedProperty( table, NODETYPE_TABLE, name, value );
                }
                ShowinfoMessage( "Edit operation finished sucessfully." );
                //MessageBox.Show( "Edit operation finished sucessfully." );
            }
            //if the scope is set at scope to selected tables.
            if( scope == Scope.SelectedScope )
            {
                foreach( TreeNode node in DbTree.Nodes[0].Nodes.OfType<TreeNode>( ).Where( c => c.Checked ).ToList( ) )
                {
                    Hashtable NodeTagValues = (Hashtable)node.Tag;
                    Table TableByNode = _currentDatabase.Tables[NodeTagValues["Name"].ToString( ), NodeTagValues["Schema"].ToString( )];
                    AddExtendedProperty( TableByNode, NODETYPE_TABLE, name, value );
                }
                ShowinfoMessage( "Edit operation finished sucessfully." );
                //MessageBox.Show( "Edit operation finished sucessfully." );
            }
        }
        /// <summary>
        /// Update property name and value, behavior set with IsName flag.
        /// </summary>
        /// <param name="smoObject"></param>
        /// <param name="objectType"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="isName"></param>
        private void UpdateProperty( SqlSmoObject smoObject, string objectType, string name, string value, bool isName)
        {
            //
            Smo.ExtendedPropertyCollection PropertiesCol = null;
            try
            {
                switch( objectType )
                {
                    case NODETYPE_DB:
                        Database d = (Database)smoObject;
                        PropertiesCol = d.ExtendedProperties;
                        //Update name or value based in isName flag.
                        if( isName )
                        {
                            //Recreate the property. parameter value is the new name.
                            if( PropertiesCol[name] != null )
                            {
                                string _value = PropertiesCol[name].Value.ToString( );
                                PropertiesCol[name].Drop( );
                                PropertiesCol.Add( new ExtendedProperty( smoObject, value, _value ) );
                            }
                        }
                        else
                        {
                            //Update property value.
                            if( PropertiesCol[name] != null )
                            {
                                PropertiesCol[name].Value = this.ParseValue( value );
                            }

                        }
                        d.Alter( );
                        break;
                    case NODETYPE_TABLE:
                        Table t = (Table)smoObject;
                        PropertiesCol = t.ExtendedProperties;
                        //Update name or value based in isName flag.
                        if( isName )
                        { 
                            //Remove and add new property. parameter value is the new name.
                            if( PropertiesCol[name] != null )
                            {
                                string _value = PropertiesCol[name].Value.ToString( );
                                PropertiesCol[name].Drop( );
                                PropertiesCol.Add( new ExtendedProperty( smoObject, value, _value ) );
                            }
                        }
                        else 
                        { 
                            //Update property value.
                            if( PropertiesCol[name] != null )
                            {
                                PropertiesCol[name].Value = this.ParseValue( value );
                            }
                            
                        }
                        t.Alter( );
                        break;
                    case NODETYPE_COLUMN:
                        Column c = (Column)smoObject;
                        PropertiesCol = c.ExtendedProperties;
                        //Update name or value based in isName flag.
                        if( isName )
                        {
                            //Remove and add new property. parameter value is the new name.
                            if( PropertiesCol[name] != null )
                            {
                               string _value = PropertiesCol[name].Value.ToString( );
                               PropertiesCol[name].Drop( );
                               PropertiesCol.Add( new ExtendedProperty( smoObject, value, _value ) );
                            }
                        }
                        else
                        {
                            //Update property value.
                            PropertiesCol[name].Value = this.ParseValue( value );
                        }
                        c.Alter( );
                        break;
                    default:
                        break;
                }
                PopulateExtendedProperties( PropertiesCol );
            }
            catch( Exception ex ) { ShowErrorMessage( ex.Message ); }
        }
        private void UpdatePropertyAtScope( string objectType, string name, string value, Scope scope, bool isName )
        {
            //If the scope is set to database scope.
            if( scope == Scope.DatabaseScope )
            {
                foreach( Table table in _currentDatabase.Tables )
                {
                    UpdateProperty( table, NODETYPE_TABLE, name, value, isName );
                }
                ShowinfoMessage( "Edit operation finished sucessfully." );
                //MessageBox.Show( "Edit operation finished sucessfully." );
            }
            //if the scope is set at scope to selected tables.
            if( scope == Scope.SelectedScope )
            {
                foreach( TreeNode node in DbTree.Nodes[0].Nodes.OfType<TreeNode>().Where( c=>c.Checked ).ToList() )
                {
                    Hashtable NodeTagValues = (Hashtable)node.Tag;
                    Table TableByNode = _currentDatabase.Tables[NodeTagValues["Name"].ToString( ), NodeTagValues["Schema"].ToString( )];
                    UpdateProperty( TableByNode, NODETYPE_TABLE, name, value, isName );
                }
                ShowinfoMessage( "Edit operation finished sucessfully." );
                //MessageBox.Show( "Edit operation finished sucessfully." );
            }

        }
        private void DeleteGlobalProperty( SqlSmoObject smoObject, string objectType, string name )
        {
            try
            {
                Smo.ExtendedPropertyCollection _propertiesCol = null;
                switch( objectType )
                {
                    case NODETYPE_DB:
                        Database DbObj = (Database)smoObject;
                        //
                        ProgressBar.Maximum = DbObj.Tables.Count; //ProgressBar
                        ProgressBar.Value = 0;
                        ProgressBar.Visible = true;

                        foreach( Table table in DbObj.Tables )
                        {
                            _propertiesCol = table.ExtendedProperties;
                            if( _propertiesCol[name] != null )
                            {
                                _propertiesCol[name].Drop( );
                                table.Alter( );
                            }
                            ProgressBar.PerformStep( );
                        }
                        //Rebuild properties gridview.
                        PopulateExtendedProperties( _currentTable.ExtendedProperties );
                        break;
                    case NODETYPE_TABLE:
                        Table tableObj = (Table)smoObject;
                        //
                        ProgressBar.Maximum = tableObj.Columns.Count; //ProgressBar
                        ProgressBar.Value = 0;
                        ProgressBar.Visible = true;
                        //
                        foreach( Column column in tableObj.Columns )
                        {
                            _propertiesCol = column.ExtendedProperties;
                            if( _propertiesCol[name] != null )
                            {
                                _propertiesCol[name].Drop( );
                                column.Alter( );
                            }
                            ProgressBar.PerformStep( );
                        }
                        //Rebuild properties gridview.
                        PopulateExtendedProperties( _currentColumn.ExtendedProperties );
                        break;
                    default:
                        break;
                }
                
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
            finally { ProgressBar.Visible = false; }
        }
        private void AddORMExtendedForeingKeyProperties( )
        {
            try
            {
            }
            catch( Exception ex ) { throw; }
        }
        private void AddORMExtendedProperties( Scope scope )
        {
            try
            {
                switch(scope)
                {
                    case Scope.DatabaseScope:
                        //Add ORM database properties.
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_CONNECTIONSTRING, "" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_CONTEXT_IMPORTS, "" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_CONTEXT_NAME, "$DatabaseName$DataContext" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_CONTEXT_NAMESPACE, "$DatabaseName$.Data" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_ENTITY_IMPORTS, "" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_ENTITY_NAMESPACE, "$DatabaseName$.Entities" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_GENERATE_MULTIPLE_FILES, "true" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_INCLUDE_PREVENT_DEBUG, "false" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_IS_SEALED, "true" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_IS_SERIALIZABLE, "true" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_SAVEPATH, @"c:\temp" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_INCLUDE_CRUD_FUNCTIONS, "false" );
                        AddExtendedProperty( _currentDatabase, NODETYPE_DB, ORM_OVERRIDE_CRUD_OPERATIONS, "false" );

                        _currentDatabase.Alter( );
                        //
                        foreach( Table table in _currentDatabase.Tables )
                        {
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_CRUD_DELETE, "" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_CRUD_INSERT, "" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_CRUD_UPDATE, "" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_ENTITY_NAME, "$TableName$" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_ENTITY_PLURALNAME, "$TableName$s" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_ENTITY_IS_SEALED, "true" );
                            AddExtendedProperty( table, NODETYPE_TABLE, ORM_ENTITY_IS_SERIALIZED, "true" );
                        }
                        break;
                    default:
                        break;
                }
                ShowConfirmationMessage( "Extended properties added successfully." );
            }
            catch( Exception ex ) { throw; }
        }
        #endregion

        #region Database Objects Managment
        private void PopulateServers( )
        {
            XElement XServers = XElement.Load( "Servers.xml" );
            foreach( var item in XServers.Elements( "Server" ) )
            {
                ServersList.Items.Add( item.Attribute( "Name" ).Value );
            }
        }
        /// <summary>
        /// Fill de database drop down control.
        /// </summary>
        private void PopulateDatabases( )
        {
            try
            {
                ProgressBar.Maximum = _serverObject.Databases.Count; //ProgressBar
                ProgressBar.Value = 0;
                ProgressBar.Visible = true;
                //Clear control.
                DbList.Items.Clear( );
                foreach( Database item in _serverObject.Databases )
                {

                    //Fill control.
                    if( item.IsSystemObject )
                    {
                        if( ConfigValues.ViewSystemDatabases ) DbList.Items.Add( item.Name );
                    }
                    else
                    {
                        DbList.Items.Add( item.Name );
                    }
                    ProgressBar.PerformStep( );
                    //Thread.Sleep( 120 );
                }
                if( DbList.Items.Count > 0 )
                    DbList.SelectedIndex = 1;
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
            finally
            {
                ProgressBar.Visible = false;
            }
        }
        private void PopulateTables( bool refresh )
        {
            try
            {
                //---------------------------------
                string DatabaseName = DbList.Text;
                //This step is necesary to load database objects. Cant use directly in loop.
                _currentDatabase = _serverObject.Databases[DatabaseName];
                //Check if request refresh
                if( refresh )
                {
                    _currentDatabase.Refresh( ); //Force refleshing database data.
                    _currentDatabase.Tables.Refresh( ); //Force refreshing database tables (names not data).
                }

                ProgressBar.Maximum = _currentDatabase.Tables.Count; //ProgressBar
                ProgressBar.Value = 0;
                ProgressBar.Visible = true;

                //Configure treeview.
                DbTree.Nodes.Clear( );
                TreeNode DatabaseNode = DbTree.Nodes.Add( DatabaseName );
                DatabaseNode.ImageIndex = 1;
                DatabaseNode.SelectedImageIndex = 1;
                //Set object tag with values used to check the node type.
                Hashtable DatabaseTagValues = new Hashtable( );
                DatabaseTagValues.Add( "Type", NODETYPE_DB ); //Node type = database.
                DatabaseTagValues.Add( "Name", DatabaseName ); //Table name.
                DatabaseNode.Tag = DatabaseTagValues;
                
                //========================================
                //  Add database tables nodes.
                //========================================
                Hashtable TableTagValues;
                foreach( Table table in _currentDatabase.Tables )
                {
                    //Check if request refresh
                    if( refresh )
                    {
                        table.Refresh( ); //Force refreshing only table data.
                        table.Columns.Refresh( ); //Force refreshing table columns (names not properties).                   

                    }
                    //Check if it is a system table.
                    if( table.IsSystemObject )
                    {
                        //If system tables allowed.
                        if( ConfigValues.ViewSystemTables )
                        {
                            //Add node.
                            TreeNode TableNode = DatabaseNode.Nodes.Add( table.Schema + "." + table.Name );
                            TableNode.ImageIndex = 5;
                            TableNode.SelectedImageIndex = 5;
                            //Add virtually node to force show expand icon. It remove when populate columns.
                            TableNode.Nodes.Add( " " );

                            //Set object tag with values used to check the node values.
                            TableTagValues = new Hashtable( );
                            TableTagValues.Add( "Type", NODETYPE_TABLE ); //Node type = Table.
                            TableTagValues.Add( "Schema", table.Schema ); //Schema name of table.
                            TableTagValues.Add( "Name", table.Name ); //Table name.
                            TableNode.Tag = TableTagValues;
                        }
                    }
                    else
                    {
                        //Add node.
                        TreeNode TableNode = DatabaseNode.Nodes.Add( table.Schema + "." + table.Name );
                        TableNode.ImageIndex = 5;
                        TableNode.SelectedImageIndex = 5;
                        //Add virtually node to force show expand icon. It remove when populate columns.
                        TableNode.Nodes.Add( " " );

                        //Set object tag with values used to check the node values.
                        TableTagValues = new Hashtable( );
                        TableTagValues.Add( "Type", NODETYPE_TABLE ); //Node type = Table.
                        TableTagValues.Add( "Schema", table.Schema ); //Schema name of table.
                        TableTagValues.Add( "Name", table.Name ); //Table name.
                        TableNode.Tag = TableTagValues;

                    }
                    //Thread.Sleep( 120 );
                    ProgressBar.PerformStep( );
                }
                DatabaseNode.Expand( );
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
            finally
            {
                ProgressBar.Visible = false;
            }

        }
        private void PopulateColumns( TreeNode tableNode, bool refresh )
        {
            try
            {
                tableNode.Nodes.Clear( );
                Hashtable TableTag = (Hashtable)tableNode.Tag;
                Table t = _currentDatabase.Tables[TableTag["Name"].ToString( ), TableTag["Schema"].ToString( )];
                foreach( Column column in t.Columns )
                {
                    //Check if request refresh
                    if( refresh )
                    {
                        column.Refresh( ); //Force refreshing column data.
                    }
                    //Add node, set tag value to  nodetype "Column"
                    TreeNode ColumnNode = tableNode.Nodes.Add( column.Name );
                    ColumnNode.ToolTipText = column.DataType.ToString( );
                    if( column.InPrimaryKey )
                    {
                        ColumnNode.ImageIndex = 3;
                        ColumnNode.SelectedImageIndex = 3;
                    }
                    else
                    {
                        ColumnNode.ImageIndex = 0;
                        ColumnNode.SelectedImageIndex = 0;
                    }

                    //Set the tag object.
                    Hashtable ColumnTag = new Hashtable( ); //Tag object host a hashtable.
                    ColumnTag.Add( "Type", NODETYPE_COLUMN ); //Node type Column.
                    ColumnTag.Add( "Name", column.Name ); //Column name.
                    ColumnNode.Tag = ColumnTag;

                }
            }
            catch( SqlException ex ) { MessageBox.Show( ex.Message ); }
        }
        #endregion

        #region LinqToSql Generator

        #region Helpers
        public Table GetReferencedTable( ForeignKey foreignKey )
        {
            return _currentDatabase.Tables[foreignKey.ReferencedTable, foreignKey.ReferencedTableSchema];
        }
        public string GetEntityName( Table table )
        {
            return table.ExtendedProperties["ORM_EntityName"].Value.ToString( );
        }
        public string GetEntityPluralName( Table table )
        {
            return table.ExtendedProperties["ORM_EntityPluralName"].Value.ToString( );
        }
        /// <summary>
        /// Return the reference name extended propertie of the column passed.
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetColumnReferenceName( Column column )
        {
            if( column.ExtendedProperties["ORM_ReferenceName"] != null )
            {
                return column.ExtendedProperties["ORM_ReferenceName"].Value.ToString( );
            }
            else
            {
                return null;
            }
           
        }
        public string GetColumnReferencePluralName( Column column )
        {
            if( column.ExtendedProperties["ORM_ReferencePluralName"] != null )
            {
                return column.ExtendedProperties["ORM_ReferencePluralName"].Value.ToString( );
            }
            else
            {
                return null;
            }

        }
        public string GetParsedEnumColumnName( Column column )
        {
            return column.Name.Replace( "Enum", "" );
        }
        public string ParseForeignkeyName( string value )
        {
            return value.Replace( "FK_", "" );
        }
        public string ParseParameterName( string name )
        {
            return name.Replace( "@", "" );
        }
        /// <summary>
        /// Get the equivalent clr type of Sql data type.
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetClrType( Column column )
        {
            string ClrType = string.Empty;
            if( column != null )
            {
                switch( column.DataType.SqlDataType.ToString( ).ToLower( ) )
                {
                    case "xml":
                        ClrType = "XElement";
                        break;
                    case "binary":
                    case "varbinary":
                    case "varbinarymax":
                    case "image":
                        ClrType = "System.Data.Linq.Binary";
                        break;
                    case "varchar":
                    case "varcharmax":
                    case "nvarchar":
                    case "nvarcharmax":
                    case "char":
                    case "nchar":
                    case "text":
                    case "ntext":
                        ClrType = "string";
                        break;
                    case "timestamp":
                        ClrType = "byte[]";
                        break;
                    case "datetime":
                    case "date":
                    case "smalldatetime":
                        ClrType = "System.DateTime";
                        break;
                    case "datetimeoffset":
                        ClrType = "System.DateTimeOffset";
                        break;
                    case "decimal":
                    case "money":
                    case "smallmoney":
                    case "numeric":
                        ClrType = "decimal";
                        break;
                    case "float":
                    case "real":
                        ClrType = "double";
                        break;
                    case "bigint":
                        ClrType = "long";
                        break;
                    case "int":
                        ClrType = "int";
                        break;
                    case "smallint":
                        ClrType = "short";
                        break;
                    case "tinyint":
                        ClrType = "byte";
                        break;
                    case "bit":
                        ClrType = "bool";
                        break;
                    case "uniqueidentifier":
                        ClrType = "System.Guid";
                        break;
                    case "time":
                        ClrType = "System.TimeSpan";
                        break;
                    default:
                        ClrType = "System.Object";
                        break;
                }
            }
            return ClrType;
        }
        /// <summary>
        /// Parse Sql data types to clr types.
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetNullableClrType( Column column )
        {

            string ClrType = string.Empty;
            if( column != null )
            {
                switch( column.DataType.SqlDataType.ToString( ).ToLower( ) )
                {
                    case "xml":
                        ClrType = "XElement";
                        break;
                    case "binary":
                    case "varbinary":
                    case "varbinarymax":
                    case "image":
                        ClrType = "System.Data.Linq.Binary";
                        break;
                    case "varchar":
                    case "varcharmax":
                    case "nvarchar":
                    case "nvarcharmax":
                    case "char":
                    case "nchar":
                    case "text":
                    case "ntext":
                        ClrType = "string";
                        break;
                    case "timestamp":
                        ClrType = "byte[]";
                        break;
                    case "datetime":
                    case "date":
                    case "smalldatetime":
                        ClrType = "System.DateTime";
                        break;
                    case "datetimeoffset":
                        ClrType = "System.DateTimeOffset";
                        break;
                    case "decimal":
                    case "money":
                    case "smallmoney":
                    case "numeric":
                        ClrType = "decimal";
                        break;
                    case "float":
                    case "real":
                        ClrType = "double";
                        break;
                    case "bigint":
                        ClrType = "long";
                        break;
                    case "int":
                        ClrType = "int";
                        break;
                    case "smallint":
                        ClrType = "short";
                        break;
                    case "tinyint":
                        if( column.Name.Contains( "Enum" ) )
                        {
                            ClrType = column.Name.Replace("Enum","") + "Enum";
                        }
                        else
                        {
                            ClrType = "Byte";
                        }
                        break;
                    case "bit":
                        ClrType = "bool";
                        break;
                    case "uniqueidentifier":
                        ClrType = "System.Guid";
                        break;
                    case "time":
                        ClrType = "System.TimeSpan";
                        break;
                    default:
                        ClrType = "System.Object";
                        break;
                }
                if( ( !column.Nullable ) || ClrType == "string" || ClrType == "System.Object" || ClrType == "XElement" || ClrType == "System.Data.Linq.Binary" )
                    return ClrType;
                else
                    //return "System.Nullable<" + systemType + ">";
                    return string.Format( "System.Nullable<{0}>", ClrType );
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// Not used.
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetDbTypeAttribute( Column column )
        {
            string columnDbType = column.DataType.ToString( );
            //
            if( column.DataType.ToString().Contains( "char" ) )
                columnDbType += String.Format( "({0})", column.DataType.MaximumLength== -1 ? "MAX" : column.DataType.MaximumLength.ToString( ) );
            //
            if( !column.Nullable ) { columnDbType += " NOT NULL"; }
            //
            if( column.Identity)
            {
               columnDbType += " IDENTITY";
            }
            return columnDbType;
        }
        public string GetSimpleDbType( Column column )
        {
            string columnDbType = column.DataType.ToString( );
            //
            if( column.DataType.ToString( ).Contains( "char" ) )
                columnDbType += String.Format( "({0})", column.DataType.MaximumLength == -1 ? "MAX" : column.DataType.MaximumLength.ToString( ) );
            return columnDbType;
        }
        public string GetColumnKeyList(ForeignKeyColumnCollection keys )
        {
            List<string> list = new List<string>( );
            foreach( Column column in keys )
                list.Add( column.Name );
            return String.Join( ", ", list.ToArray( ) );
        }
        public string Indent( string value, int level )
        {
            string Result = new String( ' ', level );
            return string.Concat( Result, value );
        }
        #endregion  

        /// <summary>
        /// Retrieve the ContextNamespace value.
        /// </summary>
        /// <returns></returns>
        public string GetContextNamespace( )
        {
            if( _currentDatabase.ExtendedProperties[ORM_CONTEXT_NAMESPACE] != null )
            {
                return _currentDatabase.ExtendedProperties[ORM_CONTEXT_NAMESPACE].Value.ToString( );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenContextNamespace;
            }
        }
        /// <summary>
        /// Retrieve the context name extended property value.
        /// </summary>
        /// <returns></returns>
        public string GetContextName( )
        {
            if( _currentDatabase.ExtendedProperties[ORM_CONTEXT_NAME] != null )
            {
                return _currentDatabase.ExtendedProperties[ORM_CONTEXT_NAME].Value.ToString( );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenContextName;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetEntityNamespace( )
        {
            if( _currentDatabase.ExtendedProperties[ORM_ENTITY_NAMESPACE] != null )
            {
                return _currentDatabase.ExtendedProperties[ORM_ENTITY_NAMESPACE].Value.ToString( );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenEntityNamespace;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetSavePath( )
        {
            if( _currentDatabase.ExtendedProperties[ORM_SAVEPATH] != null )
            {
                return _currentDatabase.ExtendedProperties[ORM_SAVEPATH].Value.ToString( );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenSavePath;
            }
        }
        public string GetContextImports( )
        {
            if( _currentDatabase.ExtendedProperties[ORM_CONTEXT_IMPORTS] != null )
            {
                return _currentDatabase.ExtendedProperties[ORM_CONTEXT_IMPORTS].Value.ToString( );
            }
            else
            {
                return string.Empty;
            }
        }
        public string GetEntityImports( )
        {
            return _currentDatabase.ExtendedProperties["ORM_EntityImports"].Value.ToString( );
        }
        public string GetBaseClassProperty( )
        {
            if( _currentDatabase.ExtendedProperties["ORM_BaseClass"].Value != null )
            {
                return _currentDatabase.ExtendedProperties["ORM_BaseClass"].Value.ToString( ) + ", ";
            }
            else
            {
                return string.Empty;
            }
        }
        public bool GetGenerateMultipleClassesOption( )
        {
            if( _currentDatabase.ExtendedProperties["ORM_GenerateMultipleClasses"] != null )
            {
                return Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_GenerateMultipleClasses"].Value );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenGenerateMultipleClasses;
            }
        }
        public bool GetOnlySelectedTablesOption( )
        {
            if( _currentDatabase.ExtendedProperties["ORM_OnlySelectedTables"] != null )
            {
                return Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_OnlySelectedTables"].Value );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenOnlySelectedTables;
            }
        }
        public bool GetIsSealedOption( )
        {
            if( _currentDatabase.ExtendedProperties["ORM_IsSealed"] != null )
            {
                //if serializable option is set at database level
                if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IsSealed"].Value ) )
                {
                    //At database level is true.
                    return true;
                }
                else
                {
                    //At database level is false.
                    return false;
                }
            }
            else
            {
                //If IsSealed set as setting.
                if( Properties.Settings.Default.LqGenIsSealed )
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        public bool GetIsSealedOption( Table table )
        {
            if( table.ExtendedProperties["ORM_IsSealed"] != null )
            {
                //if serializable option is set at entity level
                if( Convert.ToBoolean( table.ExtendedProperties["ORM_IsSealed"].Value ) )
                {
                    //at table level is true.
                    return true;
                }
                else
                {
                    //At table level is false.
                    return false;
                }
            }
            //IsSeale does not exist at table level.
            else
            {
                if( _currentDatabase.ExtendedProperties["ORM_IsSealed"] != null )
                {
                    //if serializable option is set at database level
                    if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IsSealed"].Value ) )
                    {
                        //At database level is true.
                        return true;
                    }
                    else
                    {
                        //At database level is false.
                        return false;
                    }
                }
                else
                {
                    //If IsSealed set as setting.
                    if( Properties.Settings.Default.LqGenIsSealed )
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }
        public bool GetIsSerializableOption( )
        {
            //Check if exist at database level.
            if( _currentDatabase.ExtendedProperties["ORM_IsSerializable"] != null )
            {
                //if serializable option is set at database level
                if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IsSerializable"].Value ) )
                {
                    return true;
                }
                else
                {
                    //at database level is false.
                    return false;
                }
            }
            else
            {
                //If serialiableis set as setting.
                if( Properties.Settings.Default.LqGenIsSerializable )
                {
                    //finally at setting is true.
                    return true;
                }
                else
                {
                    //finally at setting is false.
                    return false;
                }
            }
        }
        public bool GetIncludeCRUDFunctionsOption( )
        {
            //Check if exist at database level.
            if( _currentDatabase.ExtendedProperties["ORM_IncludeCRUDFunctions"] != null )
            {
                //if serializable option is set at database level
                if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IncludeCRUDFunctions"].Value ) )
                {
                    return true;
                }
                else
                {
                    //at database level is false.
                    return false;
                }
            }
            else
            {
                //If serialiableis set as setting.
                if( Properties.Settings.Default.LqGenIncludeCRUD)
                {
                    //finally at setting is true.
                    return true;
                }
                else
                {
                    //finally at setting is false.
                    return false;
                }
            }
        }
        public bool GetOverrideCRUDOperationsOption( )
        {
            //Check if exist at database level.
            if( _currentDatabase.ExtendedProperties["ORM_OverrideCRUDOperations"] != null )
            {
                //if serializable option is set at database level
                if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_OverrideCRUDOperations"].Value ) )
                {
                    return true;
                }
                else
                {
                    //at database level is false.
                    return false;
                }
            }
            else
            {
                //If serialiableis set as setting.
                if( Properties.Settings.Default.LqGenOverriteCRUD)
                {
                    //finally at setting is true.
                    return true;
                }
                else
                {
                    //finally at setting is false.
                    return false;
                }
            }
        }
        public string ParseHelpEntityDescription( string value )
        {
            throw new NotImplementedException( );
        }
        public string GetTableDescription( Table table )
        {
            return table.ExtendedProperties[Properties.Settings.Default.DescriptionPropertyName].Value.ToString( );
        }
        public string GetConnectionAccessCode( )
        {
            return _currentDatabase.ExtendedProperties["ORM_ConnectionStringName"].Value.ToString( );
        }
        /// <summary>
        /// Get the seriablizable option from table, database or setting.
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public bool GetIsSerializableOption( Table table )
        {
            if( table.ExtendedProperties["ORM_IsSerializable"] != null )
            {
                //if serializable option is set at entity level
                if( Convert.ToBoolean( table.ExtendedProperties["ORM_IsSerializable"].Value ) )
                {
                    return true;
                }
                //Is false;
                else
                {
                    //at table level is false.
                    return false;
                }
            }
            //IsSealed not exist at table level.
            else
            {
                //Check if exist at database level.
                if( _currentDatabase.ExtendedProperties["ORM_IsSerializable"] != null )
                {
                    //if serializable option is set at database level
                    if( Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IsSerializable"].Value ) )
                    {
                        return true;
                    }
                    else
                    {
                        //at database level is false.
                        return false;
                    }
                }
                else
                {
                    //If serialiableis set as setting.
                    if( Properties.Settings.Default.LqGenIsSerializable )
                    {
                        //finally at setting is true.
                        return true;
                    }
                    else
                    {
                        //finally at setting is false.
                        return false;
                    }
                }
            }
            
            
        }

        public bool GetPreventingDebugOption( )
        {
            if( _currentDatabase.ExtendedProperties["ORM_IncludePreventingDebug"] != null )
            {
                return Convert.ToBoolean( _currentDatabase.ExtendedProperties["ORM_IncludePreventingDebug"].Value );
            }
            else
            {
                //If not exist the database property uses general preference value.
                return Properties.Settings.Default.LqGenPreventDebug;
            }
        }
        public string GetAttributePrimaryKey( Column column )
        {
            if( column.Identity )
            {  
                return ", AutoSync=AutoSync.OnInsert, IsDbGenerated=true, DbType=\"Int NOT NULL IDENTITY\"";  
            }
            if( column.RowGuidCol )
            {
                return ", AutoSync=AutoSync.OnInsert, IsDbGenerated=true, DbType=\"uniqueidentifier not null\"";   
            }
            return string.Empty;
        }
        public Dictionary<Table, List<ForeignKey>> GetReverseForeignKeys( )
        {
            //Build a dictionary to store referenced keys by foreignKeys to coding EntityRefs.
            Dictionary<Table, List<ForeignKey>> _reverseForeignKeys = new Dictionary<Table, List<ForeignKey>>( );

            //Is necesary iterate through entire database to locate relationships.
            foreach( Table table in _currentDatabase.Tables )
            {
                foreach( ForeignKey ForeignKey in table.ForeignKeys )
                {
                    //Get the reference table.
                    Table _referencedTable = _currentDatabase.Tables[ForeignKey.ReferencedTable, ForeignKey.ReferencedTableSchema];
                    //
                    if( _reverseForeignKeys.ContainsKey( _referencedTable ) )
                    {
                        _reverseForeignKeys[_referencedTable].Add( ForeignKey );
                    }
                    else
                    {
                        List<ForeignKey> _foreignkeys = new List<ForeignKey>( );
                        _foreignkeys.Add( ForeignKey );
                        _reverseForeignKeys.Add( _referencedTable, _foreignkeys );
                    }
                }
            }
            return _reverseForeignKeys;
        }
        public string GetDatacontextClassCode( List<Table> tables )
        {
            try
            {
                StringBuilder Output = new StringBuilder( );
                Output.AppendLine( GetContextImports( ) );
                Output.AppendLine( );
                Output.AppendLine( string.Format( "namespace {0}", GetContextNamespace( ) ) );
                Output.AppendLine( "{" );
                Output.AppendLine( Indent( string.Format( "[DatabaseAttribute(Name=\"{0}\")]", _currentDatabase.Name ), 2 ) );
                Output.AppendLine( Indent( string.Format( "public {0} partial class  {1} : DataContext", GetIsSealedOption( ) ? "sealed" : "", GetContextName( ) ), 2 ) );
                Output.AppendLine( Indent( "{", 2 ) );
                Output.AppendLine( Indent( "private static MappingSource mappingSource = new AttributeMappingSource( );", 4 ) );
                #region Ctors
                //Ctors
                Output.AppendLine( Indent( "#region Constructors", 4 ) );
                //Ctor1
                if( GetPreventingDebugOption( ) )
                    Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 4 ) );
                Output.AppendLine( Indent( string.Format( "public {0}() : base( {1}, mappingSource)", GetContextName( ), GetConnectionAccessCode( ) ), 4 ) );
                Output.AppendLine( Indent( "{", 4 ) );
                Output.AppendLine( Indent( "OnCreated( );", 6 ) );
                Output.AppendLine( Indent( "}", 4 ) );
                //Ctor2
                if( GetPreventingDebugOption( ) )
                    Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 4 ) );
                Output.AppendLine( Indent( string.Format( "public {0}( string connection ) : base( connection, mappingSource )", GetContextName( ) ), 4 ) );
                Output.AppendLine( Indent( "{", 4 ) );
                Output.AppendLine( Indent( "OnCreated( );", 6 ) );
                Output.AppendLine( Indent( "}", 4 ) );
                //Ctor3
                if( GetPreventingDebugOption( ) )
                    Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 4 ) );
                Output.AppendLine( Indent( string.Format( "public {0}( string connection, MappingSource mappingSource) : base( connection, mappingSource )", GetContextName( ) ), 4 ) );
                Output.AppendLine( Indent( "{", 4 ) );
                Output.AppendLine( Indent( "OnCreated( );", 6 ) );
                Output.AppendLine( Indent( "}", 4 ) );
                //Ctor4
                if( GetPreventingDebugOption( ) )
                    Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 4 ) );
                Output.AppendLine( Indent( string.Format( "public {0}( IDbConnection connection ) : base( connection, mappingSource )", GetContextName( ) ), 4 ) );
                Output.AppendLine( Indent( "{", 4 ) );
                Output.AppendLine( Indent( "OnCreated( );", 6 ) );
                Output.AppendLine( Indent( "}", 4 ) );
                //Ctor5
                if( GetPreventingDebugOption( ) )
                    Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 4 ) );
                Output.AppendLine( Indent( string.Format( "public {0}( IDbConnection connection, MappingSource mappingSource) : base( connection, mappingSource )", GetContextName( ) ), 4 ) );
                Output.AppendLine( Indent( "{", 4 ) );
                Output.AppendLine( Indent( "OnCreated( );", 6 ) );
                Output.AppendLine( Indent( "}", 4 ) );
                Output.AppendLine( Indent( "#endregion", 4 ) );
                #endregion
                #region Extend
                //Extensibility
                Output.AppendLine( Indent( "#region Extensibility", 4 ) );
                Output.AppendLine( Indent( "partial void OnCreated();", 4 ) );
                Output.AppendLine( Indent( "#endregion", 4 ) );
                #endregion
                #region Tables
                //Tables
                Output.AppendLine( Indent( "#region Tables", 4 ) );
                foreach( Table table in tables )
                {
                    Output.AppendLine( Indent( "///", 4 ) );
                    Output.AppendLine( Indent( string.Format( "///Table {0}", table.Name ), 4 ) );
                    Output.AppendLine( Indent( "///", 4 ) );
                    Output.AppendLine( Indent( string.Format( "public Table<{0}> {1}", GetEntityName( table ), GetEntityPluralName( table ) ), 4 ) );
                    Output.AppendLine( Indent( "{", 4 ) );
                    Output.AppendLine( Indent( "get", 6 ) );
                    Output.AppendLine( Indent( "{", 6 ) );
                    Output.AppendLine( Indent( string.Format( "return this.GetTable<{0}>();", GetEntityName( table ) ), 8 ) );
                    Output.AppendLine( Indent( "}", 6 ) );
                    Output.AppendLine( Indent( "}", 4 ) );
                }
                Output.AppendLine( Indent( "#endregion", 4 ) );
                #endregion
                #region Functions
                //Functions
                Output.AppendLine( Indent( "#region Functions", 4 ) );
                if( GetIncludeCRUDFunctionsOption( ) )
                {
                    foreach( Table table in tables )
                    {
                        Output.AppendLine( Indent( "#region " + table.Name, 6 ) );
                        #region InsertFunction
                        Output.AppendLine( Indent( "//Insert", 6 ) );
                        //if exist a Crud insert defined.
                        if( table.ExtendedProperties[ORM_CRUD_INSERT] != null )
                        {
                            string FunctionName = table.ExtendedProperties[ORM_CRUD_INSERT].Value.ToString( );
                            //If exist a stored procedures to mapping.
                            if( _currentDatabase.StoredProcedures.OfType<StoredProcedure>( ).Where( c => c.Name == FunctionName ).Count( ) > 0 )
                            {
                                //Get stored procedure input parameters.
                                StoredProcedureParameterCollection Parameters = _currentDatabase.StoredProcedures
                                                                                .OfType<StoredProcedure>( )
                                                                                .Where( c => c.Name == FunctionName )
                                                                                .Single( ).Parameters;
                                int i = 1;
                                //If must override runtime insert
                                if( GetOverrideCRUDOperationsOption( ) )
                                {

                                    Output.AppendLine( Indent( string.Format( "private void Insert{0}({0} obj)", GetEntityName( table ) ), 6 ) );
                                    Output.AppendLine( Indent( "{", 6 ) );
                                    Output.AppendLine( Indent( string.Format( "this.Crear{0}(", GetEntityName( table ) ), 10 ) );
                                    foreach( Parameter parameter in Parameters )
                                    {
                                        Output.AppendLine( Indent( string.Format( "({0}) obj.{1}{2}", GetNullableClrType( table.Columns[parameter.Name.Replace( "@", "" )] ), parameter.Name.Replace( "@", "" ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                        i++;
                                    }

                                    //        

                                    Output.AppendLine( Indent( "}", 6 ) );
                                }
                                else
                                {
                                    Output.AppendLine( Indent( string.Format( "partial void Insert{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                                }
                                Output.AppendLine( Indent( string.Format( "[Function(Name=\"{0}.{1}\")]", table.Schema, FunctionName ), 6 ) );
                                Output.AppendLine( Indent( string.Format( "public ISingleResult<{0}> Crear{0}(", GetEntityName( table ) ), 6 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "[Parameter(Name=\"{0}\", DbType=\"{1}\")] {2} {0}{3}", ParseParameterName( parameter.Name ), GetSimpleDbType( table.Columns[ParseParameterName( parameter.Name )] ), GetNullableClrType( table.Columns[ParseParameterName( parameter.Name )] ), Parameters.Count > i ? "," : ")" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( "{", 6 ) );
                                Output.AppendLine( Indent( "IExecuteResult result = ExecuteMethodCall(this, (MethodInfo) MethodInfo.GetCurrentMethod(),", 8 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "{0}{1}", ParseParameterName( parameter.Name ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( string.Format( "return (ISingleResult<{0}>) result.ReturnValue;", GetEntityName( table ) ), 8 ) );
                                Output.AppendLine( Indent( "}", 6 ) );


                            }
                            else
                            {
                                Output.AppendLine( Indent( string.Format( "partial void Insert{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                            }
                        }
                        else
                        {
                            Output.AppendLine( Indent( string.Format( "partial void Insert{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                        }
                        
                        #endregion
                        #region UpdateFunction
                        Output.AppendLine( Indent( "//Update", 6 ) );
                        
                        //if exist Crud update extended property.
                        if( table.ExtendedProperties[ORM_CRUD_UPDATE] != null )
                        {
                            string FunctionName = table.ExtendedProperties[ORM_CRUD_UPDATE].Value.ToString( );
                            //If exist a stored procedures to mapping.
                            if( _currentDatabase.StoredProcedures.OfType<StoredProcedure>( ).Where( c => c.Name == FunctionName ).Count( ) > 0 )
                            {
                                //Get stored procedure input parameters.
                                StoredProcedureParameterCollection Parameters = _currentDatabase.StoredProcedures.OfType<StoredProcedure>( ).Where( c => c.Name == FunctionName ).Single( ).Parameters;


                                int i = 1;
                                //If must override runtime update
                                if( GetOverrideCRUDOperationsOption( ) )
                                {
                                    Output.AppendLine( Indent( string.Format( "private void Update{0}({0} obj)", GetEntityName( table ) ), 6 ) );
                                    Output.AppendLine( Indent( "{", 6 ) );
                                    Output.AppendLine( Indent( string.Format( "this.Actualizar{0}(", GetEntityName( table ) ), 10 ) );
                                    foreach( Parameter parameter in Parameters )
                                    {
                                        Output.AppendLine( Indent( string.Format( "({0}) obj.{1}{2}", GetNullableClrType( table.Columns[parameter.Name.Replace( "@", "" )] ), parameter.Name.Replace( "@", "" ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                        i++;
                                    }

                                    //        

                                    Output.AppendLine( Indent( "}", 6 ) );
                                }else
                                {
                                    Output.AppendLine( Indent( string.Format( "partial void Update{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                                }
                                Output.AppendLine( Indent( string.Format( "[Function(Name=\"{0}.{1}\")]", table.Schema, FunctionName ), 6 ) );
                                Output.AppendLine( Indent( string.Format( "public int? Actualizar{0}(", GetEntityName( table ) ), 6 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "[Parameter(Name=\"{0}\", DbType=\"{1}\")] {2} {0}{3}", ParseParameterName( parameter.Name ), GetSimpleDbType( table.Columns[ParseParameterName( parameter.Name )] ), GetNullableClrType( table.Columns[ParseParameterName( parameter.Name )] ), Parameters.Count > i ? "," : ")" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( "{", 6 ) );
                                Output.AppendLine( Indent( "IExecuteResult result = ExecuteMethodCall(this, (MethodInfo) MethodInfo.GetCurrentMethod(),", 8 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "{0}{1}", ParseParameterName( parameter.Name ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( string.Format( "return (int?) result.ReturnValue;", GetEntityName( table ) ), 8 ) );
                                Output.AppendLine( Indent( "}", 6 ) );

                            }
                            else
                            {
                                Output.AppendLine( Indent( string.Format( "partial void Update{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                            }
                        }
                        else
                        {
                            Output.AppendLine( Indent( string.Format( "partial void Update{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                        }
                        
                        #endregion
                        #region DeleteFunction
                        Output.AppendLine( Indent( "//Delete", 6 ) );
                        
                        if( table.ExtendedProperties[ORM_CRUD_DELETE] != null )
                        {

                            string FunctionName = table.ExtendedProperties[ORM_CRUD_DELETE].Value.ToString( );
                            //If exist a stored procedures to mapping.
                            if( _currentDatabase.StoredProcedures.OfType<StoredProcedure>( ).Where( c => c.Name == FunctionName ).Count( ) > 0 )
                            {
                                //Get stored procedure input parameters.
                                StoredProcedureParameterCollection Parameters = _currentDatabase.StoredProcedures.OfType<StoredProcedure>( ).Where( c => c.Name == FunctionName ).Single( ).Parameters;


                                int i = 1;
                                //If must override runtime delete
                                if( GetOverrideCRUDOperationsOption( ) )
                                {
                                    Output.AppendLine( Indent( string.Format( "private void Delete{0}({0} obj)", GetEntityName( table ) ), 6 ) );
                                    Output.AppendLine( Indent( "{", 6 ) );
                                    Output.AppendLine( Indent( string.Format( "this.Eliminar{0}(", GetEntityName( table ) ), 10 ) );
                                    foreach( Parameter parameter in Parameters )
                                    {
                                        Output.AppendLine( Indent( string.Format( "({0}) obj.{1}{2}", GetNullableClrType( table.Columns[parameter.Name.Replace( "@", "" )] ), parameter.Name.Replace( "@", "" ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                        i++;
                                    }
                                    //        

                                    Output.AppendLine( Indent( "}", 6 ) );
                                }else
                                {
                                    Output.AppendLine( Indent( string.Format( "partial void Delete{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                                }
                                Output.AppendLine( Indent( string.Format( "[Function(Name=\"{0}.{1}\")]", table.Schema, FunctionName ), 6 ) );
                                Output.AppendLine( Indent( string.Format( "public int? Eliminar{0}(", GetEntityName( table ) ), 6 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "[Parameter(Name=\"{0}\", DbType=\"{1}\")] {2} {0}{3}", ParseParameterName( parameter.Name ), GetSimpleDbType( table.Columns[ParseParameterName( parameter.Name )] ), GetNullableClrType( table.Columns[ParseParameterName( parameter.Name )] ), Parameters.Count > i ? "," : ")" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( "{", 6 ) );
                                Output.AppendLine( Indent( "IExecuteResult result = ExecuteMethodCall(this, (MethodInfo) MethodInfo.GetCurrentMethod(),", 8 ) );
                                i = 1;
                                foreach( Parameter parameter in Parameters )
                                {
                                    Output.AppendLine( Indent( string.Format( "{0}{1}", ParseParameterName( parameter.Name ), Parameters.Count > i ? "," : ");" ), 14 ) );
                                    i++;
                                }
                                Output.AppendLine( Indent( string.Format( "return (int?) result.ReturnValue;", GetEntityName( table ) ), 8 ) );
                                Output.AppendLine( Indent( "}", 6 ) );

                            }
                            else
                            {
                                Output.AppendLine( Indent( string.Format( "partial void Delete{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                            }
                        }
                        else
                        {
                            Output.AppendLine( Indent( string.Format( "partial void Delete{0}({0} instance);", GetEntityName( table ) ), 6 ) );
                        }
                        
                        #endregion
                        Output.AppendLine( Indent( "#endregion", 6 ) );
                    }
                }
                else
                {
                    foreach( Table table in tables )
                    {
                        Output.AppendLine( Indent( "#region " + table.Name, 6 ) );
                        Output.AppendLine( Indent( string.Format( "partial void Insert{0}( {0} instance );", GetEntityName( table ) ), 6 ) );
                        Output.AppendLine( Indent( string.Format( "partial void Update{0}( {0} instance );", GetEntityName( table ) ), 6 ) );
                        Output.AppendLine( Indent( string.Format( "partial void Delete{0}( {0} instance );", GetEntityName( table ) ), 6 ) );
                        Output.AppendLine( Indent( "#endregion", 6 ) );
                    }
                }
                Output.AppendLine( Indent( "#endregion", 4 ) );
                #endregion
                //
                Output.AppendLine( Indent( "}", 2 ) );
                Output.AppendLine( "}" );
                return Output.ToString( );
            }
            catch( Exception ex ) { throw; }
        }
        public string GetEntityClassCode( Table table, List<Table> tables )
        {
           
            //Initializations
            Dictionary<Table, List<ForeignKey>> _reverseForeignKeys = GetReverseForeignKeys( );
            //
            StringBuilder Output = new StringBuilder( );
            Output.AppendLine( GetEntityImports() );            
            Output.AppendLine(  );
            Output.AppendLine( string.Format( "namespace {0}", GetEntityNamespace( ) ) );
            Output.AppendLine( "{" );
            Output.AppendLine( Indent( "///<Summary>", 2 ) );
            Output.AppendLine( Indent( string.Format( "///{0}", ""), 2 ) );
            Output.AppendLine( Indent( "///</Summary>", 2 ) );
            Output.AppendLine( Indent( string.Format( "[Table(Name=\"{0}.{1}\")]", table.Schema, table.Name ), 2 ) );
            if( GetIsSerializableOption( table ) )
            {
                Output.AppendLine( Indent( string.Format( "[DataContract()][KnownType(typeof({0}))]", GetEntityName( table ) ), 2 ) );             
            }
            
            if( GetIsSealedOption( table ) )
            {
                Output.AppendLine( Indent( string.Format( "public sealed partial class {0} :{1} INotifyPropertyChanging, INotifyPropertyChanged", GetEntityName( table ), GetBaseClassProperty() ), 2 ) );
            }
            else
            {
                Output.AppendLine( Indent( string.Format( "public partial class {0} :{1} INotifyPropertyChanging, INotifyPropertyChanged", GetEntityName( table ), GetBaseClassProperty( ) ), 2 ) );
            }
            Output.AppendLine( Indent( "{", 2 ) );
            
            //Variables used in ab above code.
            int DataMemberCounter = 1;
            int Counter = 1;
            string Temp = string.Empty;
            string EntityPluralName = string.Empty;
            string EntityName = string.Empty;
            string EntityRefEntityName = string.Empty;
            string EntityRefEntityPluralName = string.Empty;
            string EntityRefGenName = string.Empty;
            string EntityGenSimpleName = string.Empty;
            string EntityGenName = string.Empty;
            //*****Fields*********
            #region Fields
            Output.AppendLine( Indent( "#region Fields", 6 ) );
            foreach( Column column in table.Columns)
            {
                Output.AppendLine( Indent( string.Format( "private {0} _{1};", GetNullableClrType( column ), column.Name ), 6 ) );          
            }
            //EntityRef fields Inicialization 
            Counter = 1;
            Temp = string.Empty;
            //
            if( table.ForeignKeys.Count > 0 )
            { 
                foreach( ForeignKey foreignKey in table.ForeignKeys )
                {
                    EntityRefEntityName = GetEntityName( GetReferencedTable( foreignKey ) );
                    EntityRefGenName = EntityRefEntityName;
                    //Obtain the referenced primarykey reference name.
                    string ReferenceKeyEntityName = GetColumnReferenceName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    //If exist use it but generate alternative name.
                    if( ReferenceKeyEntityName != null )
                    {
                        EntityRefGenName = ReferenceKeyEntityName;
                    }
                    else
                    {
                        //To avoid duplicate foreignKeys reference. Append counter.
                        if( !( string.IsNullOrEmpty( Temp ) ) )
                        {
                            if( Temp == EntityRefGenName )
                            {
                                EntityRefGenName = EntityRefEntityName + Counter;
                                Counter++;
                                Temp = EntityRefGenName;
                            }
                            else
                            {
                                EntityRefGenName = EntityRefEntityName;
                                Temp = EntityRefGenName;
                            }
                        }
                        else
                        {
                            EntityRefGenName = EntityRefEntityName;
                            Temp = EntityRefGenName;
                        }
                    }
                    Output.AppendLine( Indent( string.Format( "private EntityRef<{0}> _{1};", EntityRefEntityName, EntityRefGenName ), 6 ) );
                }
            }
            //EntitySet fields Inizialization 
            Counter = 1;
            Temp = string.Empty;
            //
            
            if( _reverseForeignKeys.ContainsKey( table ) )
            {
                foreach( ForeignKey foreignKey in _reverseForeignKeys[table] )
                {
                    EntityPluralName = GetEntityPluralName( foreignKey.Parent );
                    EntityName = GetEntityName( foreignKey.Parent );
                    EntityGenName = EntityPluralName;
                    //Obtain the referenced primarykey reference name.
                    string ColumnReferencePluralName = GetColumnReferencePluralName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    //Is exist use it but generate alternative name.
                    if( ColumnReferencePluralName != null )
                    {
                        EntityGenName = ColumnReferencePluralName;
                    }
                    else
                    {
                        //To avoid duplicate.
                        if( !( string.IsNullOrEmpty( Temp ) ) )
                        {
                            if( Temp == EntityGenName )
                            {
                                EntityGenName = EntityPluralName + Counter;
                                Counter++;
                                Temp = EntityGenName;
                            }
                            else
                            {
                                EntityGenName = EntityPluralName;
                                Temp = EntityGenName;
                            }
                        }
                        else
                        {
                            EntityGenName = EntityPluralName;
                            Temp = EntityGenName;
                        }
                    }
                    Output.AppendLine( Indent( string.Format( "private EntitySet<{0}> _{1};", EntityName, EntityGenName ), 6 ) );
                }
            }
            Output.AppendLine( Indent( "private bool serializing;", 6 ) );
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region Ctors
            Output.AppendLine( Indent( "#region Ctors", 6 ) );
            if( GetPreventingDebugOption( ) )
                Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 6 ) );
            Output.AppendLine( Indent( string.Format( "public {0}()", GetEntityName( table ) ), 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "this.Initialize();", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );
            Output.AppendLine( Indent( "private void Initialize()", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );

            //Ctor EntitySet Inizialization.
            Counter = 1;
            Temp = string.Empty;
            //
            if( _reverseForeignKeys.ContainsKey( table ) )
            {
                foreach( ForeignKey foreignKey in _reverseForeignKeys[table] )
                {
                    EntityPluralName = GetEntityPluralName( foreignKey.Parent );
                    EntityName = GetEntityName( foreignKey.Parent );
                    EntityGenName = EntityPluralName;
                    string ColumnReferencePluralName = GetColumnReferencePluralName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    //Is exist use it but generate alternative name.
                    if( ColumnReferencePluralName != null )
                    {
                        EntityGenName = ColumnReferencePluralName;
                    }
                    else
                    {
                        //To avoid duplicate.
                        if( !( string.IsNullOrEmpty( Temp ) ) )
                        {
                            if( Temp == EntityGenName )
                            {
                                EntityGenName = EntityPluralName + Counter;
                                Counter++;
                                Temp = EntityGenName;
                            }
                            else
                            {
                                EntityGenName = EntityPluralName;
                                Temp = EntityGenName;
                            }
                        }
                        else
                        {
                            EntityGenName = EntityPluralName;
                            Temp = EntityGenName;
                        }
                    }
                    Output.AppendLine( Indent( string.Format( "this._{0} = new EntitySet<{1}>(", EntityGenName, EntityName ), 8 ) );
                    Output.AppendLine( Indent( string.Format( "new Action<{0}>(this.attach_{1}),", EntityName, EntityGenName ), 14 ) );
                    Output.AppendLine( Indent( string.Format( "new Action<{0}>(this.detach_{1}));", EntityName, EntityGenName ), 14 ) );
                }
            }

            //Ctor EntityRef inizialization.
            Counter = 1;
            Temp = string.Empty;
            //
            if( table.ForeignKeys.Count > 0 )
            {
                foreach( ForeignKey foreignKey in table.ForeignKeys )
                {
                    EntityRefEntityName = GetEntityName( GetReferencedTable( foreignKey ) );
                    EntityRefGenName = EntityRefEntityName;
                    //Obtain the referenced primarykey reference name.
                    string ReferenceKeyEntityName = GetColumnReferenceName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    //If exist use it but generate alternative name.
                    if( ReferenceKeyEntityName != null )
                    {
                        EntityRefGenName = ReferenceKeyEntityName;
                    }
                    else
                    {
                        //To avoid duplicate foreignKeys reference. Append counter.
                        if( !( string.IsNullOrEmpty( Temp ) ) )
                        {
                            if( Temp == EntityRefGenName )
                            {
                                EntityRefGenName = EntityRefEntityName + Counter;
                                Counter++;
                                Temp = EntityRefGenName;
                            }
                            else
                            {
                                EntityRefGenName = EntityRefEntityName;
                                Temp = EntityRefGenName;
                            }
                        }
                        else
                        {
                            EntityRefGenName = EntityRefEntityName;
                            Temp = EntityRefGenName;
                        }
                    }
                    Output.AppendLine( Indent( string.Format( "this._{1} = default( EntityRef<{0}>);", EntityRefEntityName, EntityRefGenName ), 8) );
                }
            }
            Output.AppendLine( Indent( "OnCreated( );", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region Columns
            Output.AppendLine( Indent( "#region Columns", 6 ) );
            //Column inizialization.
            Counter = 1;
            //
            foreach( Column column in table.Columns )
            {
                
                Output.AppendLine( Indent( string.Format( "[Column(Storage=\"_{0}\", Name=\"{0}\" {1}{2}{3})]", column.Name, GetAttributePrimaryKey(column), column.InPrimaryKey ? ", IsPrimaryKey=true":"", column.Nullable ? "":", CanBeNull=false"  ), 6 ) );
                if( GetIsSerializableOption( table ) )
                {
                    Output.AppendLine( Indent( string.Format( "[DataMember(Order={0})]", DataMemberCounter ), 6 ) );
                }
                Output.AppendLine( Indent( string.Format( "public {0} {1}", GetNullableClrType( column ), column.Name ), 6 ) );             
                Output.AppendLine( Indent( "{", 6 ) );
                Output.AppendLine( Indent( "get", 8 ) );
                Output.AppendLine( Indent( "{", 8 ) );
                Output.AppendLine( Indent( string.Format( "return this._{0};", column.Name ), 10 ) );
                Output.AppendLine( Indent( "}", 8 ) );
                Output.AppendLine( Indent( "set", 8 ) );
                Output.AppendLine( Indent( "{", 8 ) );
                Output.AppendLine( Indent( string.Format( "if (this._{0} != value)", column.Name ), 10 ) );
                Output.AppendLine( Indent( "{", 10 ) );
                Output.AppendLine( Indent( string.Format( "this.On{0}Changing(value);", column.Name ), 12 ) );
                Output.AppendLine( Indent( "this.OnPropertyChanging();", 12 ) );
                Output.AppendLine( Indent( string.Format( "this._{0} = value;", column.Name ), 12 ) );
                Output.AppendLine( Indent( string.Format( "this.OnPropertyChanged(\"{0}\");", column.Name ), 12 ) );
                Output.AppendLine( Indent( string.Format( "this.On{0}Changed();", column.Name ), 12 ) );
                Output.AppendLine( Indent( "}", 10 ) );
                Output.AppendLine( Indent( "}", 8) );
                Output.AppendLine( Indent( "}", 6) );
                //
                Counter++;
                DataMemberCounter++;
            }
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region EntityRef Associations
            Output.AppendLine( Indent( "#region EntityRef Associations", 6 ) );
            //Association entityRef inizialization.
            Counter = 1;
            Temp = string.Empty;
            //
            foreach( ForeignKey foreignkey in table.ForeignKeys )
            {
                EntityName = GetEntityName(table);
                EntityPluralName = GetEntityPluralName(table);
                EntityRefEntityName = GetEntityName( GetReferencedTable( foreignkey ) );
                EntityRefEntityPluralName = GetEntityPluralName( GetReferencedTable( foreignkey ) );
                EntityRefGenName = EntityRefEntityName;
                //Obtain the referenced primarykey reference name.
                string ReferenceKeyEntityName = GetColumnReferenceName( foreignkey.Parent.Columns[foreignkey.Columns[0].Name] );
                string ReferenceKeyPluralName = GetColumnReferencePluralName( foreignkey.Parent.Columns[foreignkey.Columns[0].Name] );
                //If exist use it but generate alternative name.
                if( ReferenceKeyEntityName != null )
                {
                    //Take properties column values.
                    EntityRefGenName = ReferenceKeyEntityName;
                    EntityRefEntityPluralName = ReferenceKeyPluralName;
                }
                else
                {
                    EntityRefEntityPluralName = GetEntityPluralName( table );
                    //Generate names.
                    if( !( string.IsNullOrEmpty( Temp ) ) )
                    {
                        //if _temp3 = next foreignkey plural name.
                        if( Temp == EntityRefGenName )
                        {
                            EntityRefGenName = GetEntityName( GetReferencedTable( foreignkey ) ) + Counter;
                            Counter++;
                            Temp = EntityRefGenName;
                        }
                        else
                        {
                            EntityRefGenName = GetEntityName( GetReferencedTable( foreignkey ) );
                            Temp = EntityRefGenName;
                        }
                    }
                    else
                    {
                        EntityRefGenName = GetEntityName( GetReferencedTable( foreignkey ) );
                        Temp = EntityRefGenName;
                    }
                    
                }
                //Get the foreingKey column name.
                string ThisKey = foreignkey.Columns[0].Name; 
                //Get the column name of primary key referenced by this foreignkey.
                string OtherKey = GetReferencedTable( foreignkey ).Columns.OfType<Column>( ).Where( c => c.InPrimaryKey == true ).First( ).Name;
                //
                
                Output.AppendLine( Indent( string.Format( "[Association(Name=\"{0}\", Storage=\"_{1}\", ThisKey=\"{2}\", OtherKey=\"{3}\", {4})]", ParseForeignkeyName( foreignkey.Name ), EntityRefGenName, ThisKey, OtherKey, "IsForeignKey=true" ), 6 ) );
                
                Output.AppendLine( Indent( string.Format( "public {0} {1}", EntityRefEntityName, EntityRefGenName ), 6 ) );
                Output.AppendLine( Indent( "{", 6 ) );
                Output.AppendLine( Indent( "get", 8 ) );
                Output.AppendLine( Indent( "{", 8 ) );
                Output.AppendLine( Indent( string.Format( "return this._{0}.Entity;", EntityRefGenName ), 10 ) );
                Output.AppendLine( Indent( "}", 8) );
                Output.AppendLine( Indent( "set", 8 ) );
                Output.AppendLine( Indent( "{", 8 ) );
                Output.AppendLine( Indent( string.Format( "{0} previousValue = this._{1}.Entity;", EntityRefEntityName, EntityRefGenName ), 10 ) );
                Output.AppendLine( Indent( string.Format( "if ((previousValue != value) || (this._{0}.HasLoadedOrAssignedValue == false))", EntityRefGenName ), 10 ) );
                Output.AppendLine( Indent( "{", 10 ) );
                Output.AppendLine( Indent( "this.OnPropertyChanging();", 12 ) );
                Output.AppendLine( Indent( "if ((previousValue != null))", 12 ) );
                Output.AppendLine( Indent( "{", 12 ) );
                Output.AppendLine( Indent( string.Format( "this._{0}.Entity = null;", EntityRefGenName ), 14 ) );
                Output.AppendLine( Indent( string.Format( "previousValue.{0}.Remove(this);", EntityRefEntityPluralName ), 14 ) );
                Output.AppendLine( Indent( "}", 12 ) );
                Output.AppendLine( Indent( string.Format( "this._{0}.Entity = value;", EntityRefGenName ), 12 ) );
                Output.AppendLine( Indent( "if ((value != null))", 12 ) );
                Output.AppendLine( Indent( "{", 12 ) );
                Output.AppendLine( Indent( string.Format( "value.{0}.Add(this);", EntityRefEntityPluralName ), 14 ) );
                Output.AppendLine( Indent( string.Format( "this.{0} = value.{1};", ThisKey, OtherKey ), 14 ) );
                Output.AppendLine( Indent( "}else{", 12 ) );
                Output.AppendLine( Indent( string.Format( "this.{0} = default({1});", ThisKey, GetNullableClrType( table.Columns[ThisKey] ) ), 14 ) );
                Output.AppendLine( Indent( "}", 12 ) );
                Output.AppendLine( Indent( string.Format( "this.OnPropertyChanged(\"{0}\");", EntityRefGenName ), 12 ) );
                Output.AppendLine( Indent( "}", 10 ) );
                Output.AppendLine( Indent( "}", 8 ) );
                Output.AppendLine( Indent( "}", 6 ) );
                //Incremente member order.
                DataMemberCounter++;
            }
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region EntitySet Associations
            Output.AppendLine( Indent( "#region EntitySet Associations", 6 ) );
            //Association entitySet inizialization.
            Counter = 1;
            Temp = string.Empty;
            //
            if( _reverseForeignKeys.ContainsKey( table ) )
            {
                foreach( ForeignKey foreignKey in _reverseForeignKeys[table] )
                {
                    EntityPluralName = GetEntityPluralName( foreignKey.Parent );
                    EntityName = GetEntityName( foreignKey.Parent );
                    EntityGenName = EntityPluralName;
                    //Obtain the referenced primarykey reference name.
                    string ColumnReferencePluralName = GetColumnReferencePluralName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    string ColumnReferenceName = GetColumnReferenceName( foreignKey.Parent.Columns[foreignKey.Columns[0].Name] );
                    //Is exist use it but generate alternative name.
                    if( ColumnReferencePluralName != null )
                    {
                        EntityGenName = ColumnReferencePluralName;
                        EntityGenSimpleName = ColumnReferenceName;
                    }
                    else
                    {
                        //To avoid duplicate.
                        if( !( string.IsNullOrEmpty( Temp ) ) )
                        {
                            if( Temp == EntityGenName )
                            {
                                EntityGenName = EntityPluralName + Counter;
                                Counter++;
                                Temp = EntityGenName;
                            }
                            else
                            {
                                EntityGenName = EntityPluralName;
                                Temp = EntityGenName;
                            }
                        }
                        else
                        {
                            EntityGenName = EntityPluralName;
                            Temp = EntityGenName;
                        }
                        EntityGenSimpleName = GetEntityName( table );
                    }
                    //Get the foreingKey column name.
                    string OtherKey = foreignKey.Columns[0].Name;
                    //Get the column name of primary key referenced by this foreignkey.
                    string ThisKey = GetReferencedTable( foreignKey ).Columns.OfType<Column>( ).Where( c => c.InPrimaryKey == true ).First( ).Name;
                    
                    Output.AppendLine( Indent( string.Format( "[Association(Name=\"{0}\", Storage=\"_{1}\", OtherKey=\"{2}\", ThisKey= \"{3}\")]", ParseForeignkeyName(foreignKey.Name), EntityGenName, OtherKey, ThisKey ), 6 ) );
                    //if( GetIsSerializableOption( table ) )
                    //{
                    //    Output.AppendLine( Indent( string.Format( "[DataMember(Order={0})]", DataMemberCounter ), 6 ) );
                    //}
                    Output.AppendLine( Indent( string.Format( "public EntitySet<{0}> {1}", EntityName, EntityGenName ), 6 ) );
                    Output.AppendLine( Indent( "{", 6 ) );
                    Output.AppendLine( Indent( "get", 8 ) );
                    Output.AppendLine( Indent( "{", 8 ) );
                    Output.AppendLine( Indent( string.Format( "if ((this.serializing && (this._{0}.HasLoadedOrAssignedValues == false)))", EntityGenName ), 10 ) );
                    Output.AppendLine( Indent( "{", 10 ) );
                    Output.AppendLine( Indent( "return null;", 12 ) );
                    Output.AppendLine( Indent( "}", 10 ) );
                    Output.AppendLine( Indent( string.Format( "return this._{0};", EntityGenName ), 10 ) );
                    Output.AppendLine( Indent( "}", 8 ) );
                    Output.AppendLine( Indent( "set", 8 ) );
                    Output.AppendLine( Indent( "{", 8 ) );
                    Output.AppendLine( Indent( string.Format( "this._{0}.Assign(value);", EntityGenName ), 10 ) );
                    Output.AppendLine( Indent( "}", 8 ) );
                    Output.AppendLine( Indent( "}", 6 ) );
                    //
                    Output.AppendLine( Indent( string.Format( "private void attach_{0}({1} entity)", EntityGenName, EntityName ), 6 ) );
                    Output.AppendLine( Indent( "{", 6 ) );
                    Output.AppendLine( Indent( "this.OnPropertyChanging();", 8 ) );
                    Output.AppendLine( Indent( string.Format( "entity.{0} = this;", EntityGenSimpleName ), 8 ) );
                    Output.AppendLine( Indent( "}", 6 ) );

                    Output.AppendLine( Indent( string.Format( "private void detach_{0}({1} entity)", EntityGenName, EntityName ), 6 ) );
                    Output.AppendLine( Indent( "{", 6 ) );
                    Output.AppendLine( Indent( "this.OnPropertyChanging();", 8 ) );
                    Output.AppendLine( Indent( string.Format( "entity.{0} = null;", EntityGenSimpleName ), 8 ) );
                    Output.AppendLine( Indent( "}", 6 ) );

                    //Incremente member order.
                    DataMemberCounter++;
                }
                
            }
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region Serialization
            Output.AppendLine( Indent( "#region Serialization", 6 ) );
            Output.AppendLine( Indent( "[OnDeserializing()]", 6 ) );
            Output.AppendLine( Indent( "[System.ComponentModel.EditorBrowsableAttribute(EditorBrowsableState.Never)]", 6 ) );
            Output.AppendLine( Indent( "public void OnDeserializing(StreamingContext context)", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "this.Initialize();", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );

            Output.AppendLine( Indent( "[OnSerializing()]", 6 ) );
            Output.AppendLine( Indent( "[System.ComponentModel.EditorBrowsableAttribute(EditorBrowsableState.Never)]", 6 ) );
            Output.AppendLine( Indent( "public void OnSerializing(StreamingContext context)", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "this.serializing = true;", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );

            Output.AppendLine( Indent( "[OnSerialized()]", 6 ) );
            Output.AppendLine( Indent( "[System.ComponentModel.EditorBrowsableAttribute(EditorBrowsableState.Never)]", 6 ) );
            Output.AppendLine( Indent( "public void OnSerialized(StreamingContext context)", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "this.serializing = false;", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region Property Change Event Handling
            Output.AppendLine( Indent( "#region PropertyChange event handling", 6 ) );
            Output.AppendLine( Indent( "private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);", 6 ) );
            Output.AppendLine( Indent( "public event PropertyChangingEventHandler PropertyChanging;", 6 ) );
            Output.AppendLine( Indent( "public event PropertyChangedEventHandler PropertyChanged;", 6 ) );
            if( GetPreventingDebugOption( ) )
            {
                Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 6 ) );
            }
            Output.AppendLine( Indent( "protected void OnPropertyChanging()", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "if (this.PropertyChanging != null) this.PropertyChanging(this, emptyChangingEventArgs);", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );	
            if( GetPreventingDebugOption( ) )
            {
                Output.AppendLine( Indent( "[System.Diagnostics.DebuggerNonUserCodeAttribute()]", 6 ) );
            }
            Output.AppendLine( Indent( "protected void OnPropertyChanged(string propertyName)", 6 ) );
            Output.AppendLine( Indent( "{", 6 ) );
            Output.AppendLine( Indent( "if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));", 8 ) );
            Output.AppendLine( Indent( "}", 6 ) );
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            #region Extensibility Method Definitions
            Output.AppendLine( Indent( "#region Extensibility methods", 6 ) );
            Output.AppendLine( Indent( "partial void OnLoaded();", 6 ) );
            Output.AppendLine( Indent( "partial void OnValidate(System.Data.Linq.ChangeAction action);", 6 ) );
            Output.AppendLine( Indent( "partial void OnCreated();", 6 ) );
            foreach( Column column in table.Columns )
            {
                Output.AppendLine( Indent( string.Format( "partial void On{0}Changing({1} value);", column.Name, GetNullableClrType( column ) ), 6 ) );
                
                Output.AppendLine( Indent( string.Format( "partial void On{0}Changed();", column.Name ), 6 ) );
            }
            Output.AppendLine( Indent( "#endregion", 6 ) );
            #endregion
            Output.AppendLine( Indent( "}", 2 ) );
            Output.AppendLine( "}" );
            return Output.ToString();
        }
        public void GenerateMultipleFiles( string savePath, List<Table> tables)
        {
            ProgressBar.Maximum = tables.Count; //ProgressBar
            ProgressBar.Value = 0;
            ProgressBar.Visible = true;
            //
            

            //Write the context class.
            string DataContextPath = savePath + @"\" + GetContextName( ) + ".cs";
            using( StreamWriter Wr1 = new StreamWriter( DataContextPath ) )
            {
                Wr1.Write( GetDatacontextClassCode( tables ) );
                Wr1.Flush( );
            }
            ProgressBar.PerformStep( );
            foreach( Table table in tables )
            {
                ProgressBar.PerformStep( );
                string _filePath = savePath + @"\" + GetEntityName( table ) + ".cs";
                using( StreamWriter Wr2 = new StreamWriter( _filePath ) )
                {
                    //Pass the current table and the current table collection.
                    Wr2.Write( GetEntityClassCode( table, tables ) );
                    Wr2.Flush( );
                }
                
            }
            ProgressBar.Value = 0;
            ProgressBar.Visible = false;
            //
            //StreamWriter Wr=new StreamWriter(savePath + "
        }
        public void GenerateMultipleFiles( string savePath )
        {
            if( Directory.Exists( savePath ) )
            {
                if( Directory.GetFiles( savePath ).Count( ) > 0 )
                {
                    if( ShowConfirmationMessage("All files will be deleted. Are you agree?" ) == DialogResult.OK )
                    {

                        Directory.Delete( savePath, true );
                        Directory.CreateDirectory( savePath );
                    }
                }
            }
            else
            {
                Directory.CreateDirectory( savePath );

            }
            //Gets list of treenodes under de root node.
            if( GetOnlySelectedTablesOption( ) )
            {
                //Get the checked nodes under root node.
                List<TreeNode> _nodesCol = DbTree.Nodes[0].Nodes.OfType<TreeNode>( ).Where( c => c.Checked ).ToList();
                List<Table> _tables = new List<Table>();
                foreach (TreeNode node in _nodesCol)
	            {
            	    Hashtable _nodeTag = (Hashtable)node.Tag;
                    string _schemaName = _nodeTag["Schema"].ToString();
                    string _tableName = _nodeTag["Name"].ToString();
                    _tables.Add(_currentDatabase.Tables[_tableName, _schemaName ]);
	            }
                GenerateMultipleFiles( savePath, _tables );
                ShowinfoMessage( "Generation code was successful." );
            }
            else
            {
                //Get all nodes under root node.
                List<TreeNode> _nodesCol = DbTree.Nodes[0].Nodes.OfType<TreeNode>( ).ToList( );
                List<Table> _tables = new List<Table>();
                foreach (TreeNode node in _nodesCol)
	            {
                    Hashtable _nodeTag = (Hashtable)node.Tag;
                    string _schemaName = _nodeTag["Schema"].ToString( );
                    string _tableName = _nodeTag["Name"].ToString( );
                    _tables.Add( _currentDatabase.Tables[_tableName, _schemaName] );
	            }
                GenerateMultipleFiles( savePath, _tables );
                ShowinfoMessage( "Generation code was successful." );
            }
        }
        public void GenerateUniqueFile( string savePath )
        {
            
        }
        public void GenerateLinqToSqlClasses( )
        {
            try
            {
                string _savePath = GetSavePath( );

                //Check if it should generate multiples classes
                if( GetGenerateMultipleClassesOption( ) )
                {
                    GenerateMultipleFiles( _savePath );
                }
                else
                {
                    GenerateUniqueFile( _savePath );
                }
            }
#if DEBUG
            catch( Exception ex ) { ShowErrorMessage( ex.Message + "\n" + ex.StackTrace ); }
#else
            catch( Exception ex ) { ShowErrorMessage( ex.Message ); }
#endif
        }
        #endregion

        #region General methods
        
        #endregion

        #region SMO methods
        private string GetServerConnectionString( string serverName )
        {
            XElement XServers = XElement.Load( "Servers.xml" );
            XElement Server = (from p in XServers.Elements( "Server" )
                               where p.Attribute( "Name" ).Value == serverName
                               select p).Single();

            return Server.Element( "ConnectionString" ).Value;
        }
        
        /// <summary>
        /// This method gets column description (MS_Description) and fill field. Retrieves extended
        /// properties collection 
        /// </summary>
        /// <param name="node"></param>
        /// 
        private void GetDatabaseDescription( TreeNode node )
        {
            try
            {
                if( DbTree.SelectedNode != null )
                {

                    //Retrieve table extended properties.
                    Smo.ExtendedPropertyCollection PropCol = _currentDatabase.ExtendedProperties;
                    //Populate extended properties view.
                    PopulateExtendedProperties( PropCol );
                    //Fill de description field.
                    if( PropCol[ConfigValues.DescriptionLabel] != null )
                    {
                        //Show in text field to edit.
                        FieldDescription.Text = PropCol[ConfigValues.DescriptionLabel].Value.ToString( );
                    }
                    else
                    {
                        //Create a extended property an inizialize it to a empty value.
                        Smo.ExtendedProperty ColumnDescriptionExtProperty = new ExtendedProperty( _currentDatabase, ConfigValues.DescriptionLabel, string.Empty );
                        PropCol.Add( ColumnDescriptionExtProperty );
                        _currentDatabase.Alter( );
                        FieldDescription.Text = ColumnDescriptionExtProperty.ToString( );
                    }

                }
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void GetColumnDescription( TreeNode node )
        {
            try
            {
                if( DbTree.SelectedNode != null )
                {
                    Hashtable ParentTagValues = (Hashtable)node.Parent.Tag;
                    Hashtable TagValues = (Hashtable)node.Tag;
                    string SchemaName = ParentTagValues["Schema"].ToString( );
                    string TableName = ParentTagValues["Name"].ToString( );
                    _currentTable = _currentDatabase.Tables[TableName, SchemaName];
                    //
                    _currentColumn = _currentTable.Columns[node.Text];
                    
                    //Retrieve table extended properties.
                    Smo.ExtendedPropertyCollection PropCol = _currentColumn.ExtendedProperties;
                    //Populate extended properties view.
                    PopulateExtendedProperties( PropCol );
                    //Fill de description field.
                    if( PropCol[ConfigValues.DescriptionLabel] != null )
                    {
                        //Show in text field to edit.
                        FieldDescription.Text = PropCol[ConfigValues.DescriptionLabel].Value.ToString( );
                    }
                    else
                    {
                        //Create a extended property an inizialize it to a empty value.
                        Smo.ExtendedProperty ColumnDescriptionExtProperty = new ExtendedProperty( _currentColumn, ConfigValues.DescriptionLabel, string.Empty );
                        PropCol.Add( ColumnDescriptionExtProperty );
                        _currentColumn.Alter( );
                        FieldDescription.Text = ColumnDescriptionExtProperty.ToString( );
                    }

                }
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }     
        private void GetTableDescription( TreeNode node )
        {
            try
            {
                if( DbTree.SelectedNode != null )
                {
                    
                    Hashtable TagValues = (Hashtable)node.Tag;
                    string SchemaName = TagValues["Schema"].ToString( );
                    string TableName = TagValues["Name"].ToString( );
                    _currentTable = _currentDatabase.Tables[TableName, SchemaName];

                    //Retrieve table extended properties.
                    Smo.ExtendedPropertyCollection PropCol = _currentTable.ExtendedProperties;
                    //Populate extended properties view.
                    PopulateExtendedProperties( PropCol );
                    //Fill de description field.
                    if( PropCol[ConfigValues.DescriptionLabel] != null )
                    {
                        //Show in text field to edit.
                        FieldDescription.Text = PropCol[ConfigValues.DescriptionLabel].Value.ToString( ); 
                    }
                    else
                    {
                        //Create a extended property an inizialize it to a empty value.
                        Smo.ExtendedProperty TableDescriptionExtProperty = new ExtendedProperty( _currentTable, ConfigValues.DescriptionLabel, string.Empty );
                        PropCol.Add( TableDescriptionExtProperty );
                        _currentTable.Alter( );
                        FieldDescription.Text = TableDescriptionExtProperty.ToString( );
                    }

                }
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        /// <summary>
        /// Save object description.
        /// </summary>
        /// <param name="table"></param>
        private void SaveObjectDescription( SqlSmoObject smoObject, string objectType )
        {
            Smo.ExtendedPropertyCollection PropertiesCol = null;
            try
            {
                //
                switch( objectType )
                {
                    case NODETYPE_DB:
                        Database Db = (Database)smoObject;
                        PropertiesCol = Db.ExtendedProperties;
                        PropertiesCol[ConfigValues.DescriptionLabel].Value = FieldDescription.Text;
                        Db.Alter( );
                        break;
                    case NODETYPE_TABLE:
                        Table t = (Table)smoObject;
                        PropertiesCol = t.ExtendedProperties;
                        PropertiesCol[ConfigValues.DescriptionLabel].Value = FieldDescription.Text;
                        t.Alter( );
                        break;
                    case NODETYPE_COLUMN:
                        Column c = (Column)smoObject;
                        PropertiesCol = c.ExtendedProperties;
                        PropertiesCol[ConfigValues.DescriptionLabel].Value = FieldDescription.Text;
                        c.Alter( );
                        break;
                    default:
                        break;
                }
                PopulateExtendedProperties( PropertiesCol );
            }
            
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void SetCurrentObject( TreeNode node, string objectType )
        {
            Hashtable TagValues;
            switch( objectType )
            {
                case NODETYPE_DB:
                    //Get the metadata object to retrieve metadata values.
                    TagValues = (Hashtable)node.Tag;
                    string DatabaseName = TagValues["Name"].ToString( );
                    //Set the current object to table object.
                    _currentObject = _currentDatabase;
                    _currentObjectType = NODETYPE_DB;
                    break;
                case NODETYPE_TABLE:
                    //Get the metadata object to retrieve metadata values.
                    TagValues = (Hashtable)node.Tag;
                    string SchemaTableName = TagValues["Schema"].ToString( );
                    string TableName = TagValues["Name"].ToString( );
                    //Set the current object to table object.
                    _currentObject = _currentDatabase.Tables[TableName, SchemaTableName];
                    _currentObjectType = NODETYPE_TABLE;
                    break;
                case NODETYPE_COLUMN:
                    //Get the metadata object to retrieve metadata values.
                    TagValues = (Hashtable)node.Tag;
                    string ColumnName = TagValues["Name"].ToString( );
                    //Set the current object to table object.
                    _currentObject = _currentTable.Columns[ColumnName];
                    _currentObjectType = NODETYPE_COLUMN;
                    break;
                default:
                    break;
            }
        }
        private void Connect( )
        {
            try
            {
                
            }
            catch( SqlException ex ) { MessageBox.Show( ex.Message ); }
        }
        private void Disconnect( )
        {
            try
            {
                if( _serverConn != null )
                {
                    _serverConn.Disconnect( );
                    _serverConnected = false;
                    _serverConn = null; _conn = null; _serverObject = null;
                    ClearDatabaseControls( );
                    DisableDatabaseControls( );
                }
            }
            catch( SqlException ex ) { MessageBox.Show( ex.Message ); }
        }
        private void ActivateServerConnection( )
        {
            try
            {
                Disconnect( );
                //Check if CurrentServerConnectinString is valid.
                if( !string.IsNullOrEmpty( _currentServerConnectionString ) )
                {
                    if( _conn == null )
                    {
                        _conn = new SqlConnection( _currentServerConnectionString );
                    }
                    //if(Conn.State==ConnectionState.Closed)
                    //    Conn.Open( );
                    //this.Text = "Connected";
                    _serverConn = new ServerConnection( _conn );
                    if( _serverObject == null )
                        _serverObject = new Server( _serverConn );
                    //
                    PopulateDatabases( );
                    _serverConnected = true; //Set the current state.
                    EnableDatabaseControls( );
                }
                else
                {
                    MessageBox.Show( "Server is not selected." );
                }
            }

            catch( SqlException ex ) { MessageBox.Show( ex.Message ); }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }

        }
        #endregion

        #region Events

        #region Form events
        private void Main_Load( object sender, EventArgs e )
        {

        }
        private void Mainform_Resize( object sender, EventArgs e )
        {

        }
        #endregion

        #region Menu events
        private void disconnectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            Disconnect( );
        }
        private void exitToolStripMenuItem_Click( object sender, EventArgs e )
        {
            this.Dispose( );
        }
        private void connectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            ActivateServerConnection( );
        }
        private void aboutToolStripMenuItem_Click( object sender, EventArgs e )
        {
            About AboutForm = new About( );
            AboutForm.Show( );
        }
        private void refreshToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if(_serverConnected)
                PopulateTables( true );
        }
        
        private void ExPropContext_Opening( object sender, CancelEventArgs e )
        {
            //Enable/Disable context menu options.
            switch( _currentObjectType )
            {
                case NODETYPE_DB:
                    ExPropContext.Items["gwTableScopeDelete"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeDelete"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = false;
                    ExPropContext.Items["gwTableScopeModify"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = false;
                    ExPropContext.Items["gwSelectedScopeModify"].Enabled = false;
                    break;
                case NODETYPE_TABLE:
                    ExPropContext.Items["gwTableScopeDelete"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeDelete"].Enabled = true;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = true;
                    ExPropContext.Items["gwTableScopeModify"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = true;
                    ExPropContext.Items["gwSelectedScopeModify"].Enabled = true;
                    break;
                case NODETYPE_COLUMN:
                    ExPropContext.Items["gwTableScopeDelete"].Enabled = true;
                    ExPropContext.Items["gwDatabaseScopeDelete"].Enabled = false;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = false;
                    ExPropContext.Items["gwTableScopeModify"].Enabled = true;
                    ExPropContext.Items["gwDatabaseScopeModify"].Enabled = false;
                    ExPropContext.Items["gwSelectedScopeModify"].Enabled = false;
                    break;
                default:
                    break;
            }
           
        }
        //ContextMenu Operations
        private void ExPropContext_ItemClicked( object sender, ToolStripItemClickedEventArgs e )
        {
            switch( e.ClickedItem.Name)
            {
                case "gwTableScopeDelete":
                    if( _currentDatabase != null )
                    {
                        //Extended properties selected.
                        if( DbProperties.SelectedRows.Count > 0 )
                        {
                            //Only one selected.
                            if( DbProperties.SelectedRows.Count == 1 )
                            {
                                if( ShowConfirmationMessage("Are you sure to delete this property in all tables of the current database?") == DialogResult.OK )
                                {
                                    var PropertyName = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                                    DeleteGlobalProperty( _currentTable, NODETYPE_TABLE, PropertyName );
                                }
                            }

                        }
                    }
                    else
                    {
                        ShowAlertMessage( "None database object selected." );
                    }
                    break;
                case "gwDatabaseScopeDelete":
                    if( _currentDatabase != null )
                    {
                        
                        //Extended properties selected.
                        if( DbProperties.SelectedRows.Count > 0 )
                        {
                            //Only one selected.
                            if( DbProperties.SelectedRows.Count == 1 )
                            {
                                if( ShowConfirmationMessage( "Are you sure to delete this property in all tables of the current database?" ) == DialogResult.OK )
                                {
                                    var PropertyName = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                                    DeleteGlobalProperty( _currentDatabase, NODETYPE_DB, PropertyName );
                                }
                            }
                            
                        }
                    }
                    else
                    {
                       ShowAlertMessage( "None database object selected." );
                    }
                    break;
                case "gw":
                    break;
                default:
                    break;
            }
        }
        //Add
        private void gwScopeDatabaseAddProperty( object sender, EventArgs e )
        {
            if( _currentDatabase != null )
            {
                CreatePropertyForm GpForm = new CreatePropertyForm( );
                if( GpForm.ShowDialog( ) == DialogResult.OK )
                {
                    string _propertyName = GpForm.PropertyName;
                    string _propertyDefaultValue = GpForm.PropertyDefaultValue;
                    //Check if name o default are empty.
                    if( !string.IsNullOrEmpty( _propertyName ) )
                    {
                        AddExtendedPropertyAtScope( NODETYPE_DB, _propertyName, _propertyDefaultValue, Scope.DatabaseScope  );
                    }
                    else
                    {
                        ShowAlertMessage( "Name or defaultValue fields are empty or are invalid." );
                    }
                }
            }
            else
            {
                ShowAlertMessage( "None database object selected." );
            }
        }
        private void gwScopeTableAddProperty( object sender, EventArgs e )
        {
            if( _currentTable != null )
            {
                CreatePropertyForm GpForm = new CreatePropertyForm( );
                if( GpForm.ShowDialog( ) == DialogResult.OK )
                {
                    string _propertyName = GpForm.PropertyName;
                    string _propertyDefaultValue = GpForm.PropertyDefaultValue;
                    //Check if name o default are empty.
                    if( !string.IsNullOrEmpty( _propertyName ) 
                        )
                    {
                        AddExtendedProperty( _currentTable, NODETYPE_TABLE, _propertyName, _propertyDefaultValue );
                    }
                    else
                    {
                        ShowAlertMessage( "Name or defaultValue fields are empty." );
                    }
                }

            }
            else
            {
                ShowAlertMessage( "None table object selected." );
            }
        }
        private void gwScopeSelectedAddProperty( object sender, EventArgs e )
        {
            if( _currentDatabase != null )
            {
                CreatePropertyForm GpForm = new CreatePropertyForm( );
                if( GpForm.ShowDialog( ) == DialogResult.OK )
                {
                    string _propertyName = GpForm.PropertyName;
                    string _propertyDefaultValue = GpForm.PropertyDefaultValue;
                    //Check if name o default are empty.
                    if( !string.IsNullOrEmpty( _propertyName ) )
                    {
                        AddExtendedPropertyAtScope( NODETYPE_DB, _propertyName, _propertyDefaultValue, Scope.SelectedScope );
                    }
                    else
                    {
                        ShowAlertMessage( "Name or defaultValue fields are empty or are invalid." );
                    }
                }
            }
            else
            {
                ShowAlertMessage( "None database object selected." );
            }
        }
        private void gwScopeTableSelectedAddProperty( object sender, EventArgs e )
        {

        }
        private void generateLinqToSqlClassesToolStripMenuItem_Click( object sender, EventArgs e )
        {
            GenerateLinqToSqlClasses( );
        }
        private void preferencesToolStripMenuItem_Click( object sender, EventArgs e )
        {
            Options Op = new Options( );
            if( Op.ShowDialog( ) == DialogResult.OK )
            {
                LoadConfiguration( );
            }
        }
        //
        private void gwTableScopeDelete_Click( object sender, EventArgs e )
        {

        }
        private void gwDatabaseScopeDelete_Click( object sender, EventArgs e )
        {

        }
        private void gwTableScopeModify_Click( object sender, EventArgs e )
        {

        }
        private void gwSelectedScopeModify_Click( object sender, EventArgs e )
        {
            if( !( DbProperties.SelectedRows.Count == 0 ) )
            {
                EditPropertyForm EpForm = new EditPropertyForm( );
                EpForm.fOldName.Text = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                EpForm.fNewName.Text = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                EpForm.fOldValue.Text = DbProperties.SelectedRows[0].Cells[1].Value.ToString( );
                if( EpForm.ShowDialog( ) == DialogResult.OK )
                {
                    if( EpForm.fCheckNames.Checked )
                    {
                        if( string.IsNullOrEmpty( EpForm.OldName ) || string.IsNullOrEmpty( EpForm.NewName ) )
                        {
                            ShowAlertMessage("Can't edit because OldName or NewName has invalid values.");
                            //MessageBox.Show( "Can't edit because OldName or NewName has invalid values." );
                            return;
                        }
                        if( EpForm.OldName == EpForm.NewName )
                        {
                            ShowAlertMessage( "Can't edit because OldName or NewName values are identical." );
                            //MessageBox.Show( "Can't edit because OldName or NewName has identical values." );
                            return;
                        }
                        //Change the name recreating the property in old tables.
                        UpdatePropertyAtScope( NODETYPE_TABLE, EpForm.OldName, EpForm.NewName, Scope.SelectedScope, true );
                    }

                    if( EpForm.fCheckValues.Checked )
                    {
                        //Chanve the value.
                        UpdatePropertyAtScope( NODETYPE_TABLE, EpForm.OldValue, EpForm.NewValue, Scope.SelectedScope, false );
                    }


                }
            }
        }
        private void gwDatabaseScopeModify_Click( object sender, EventArgs e )
        {
            if( !( DbProperties.SelectedRows.Count == 0 ) )
            {
                EditPropertyForm EpForm = new EditPropertyForm( );
                EpForm.fOldName.Text = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                EpForm.fNewName.Text = DbProperties.SelectedRows[0].Cells[0].Value.ToString( );
                EpForm.fOldValue.Text = DbProperties.SelectedRows[0].Cells[1].Value.ToString( );
                
                if( EpForm.ShowDialog( ) == DialogResult.OK )
                {
                    //Wait WaitForm = new Wait( );
                    //WaitForm.Show ( );
                    if( EpForm.fCheckNames.Checked )
                    {
                        if( string.IsNullOrEmpty( EpForm.OldName ) || string.IsNullOrEmpty( EpForm.NewName ) )
                        {
                            ShowAlertMessage( "Can't edit because OldName or NewName has invalid values." );
                            //MessageBox.Show( "Can't edit because OldName or NewName has invalid values." );
                            return;
                        }
                        if( EpForm.OldName == EpForm.NewName )
                        {
                            ShowAlertMessage( "Can't edit because OldName or NewName values are identical." );
                            //MessageBox.Show( "Can't edit because OldName or NewName has identical values." );
                            return;
                        }
                        //Change the name recreating the property in old tables.
                        UpdatePropertyAtScope( NODETYPE_TABLE, EpForm.OldName, EpForm.NewName, Scope.DatabaseScope, true );
                    }

                    if( EpForm.fCheckValues.Checked )
                    {
                        //Chanve the value.
                        UpdatePropertyAtScope( NODETYPE_TABLE, EpForm.OldValue, EpForm.NewValue, Scope.DatabaseScope, false );
                    }
                    //WaitForm.Hide( );
                    //WaitForm.Dispose( );

                }
                
            }
        }
        private void gwAddORMExtendedProperties_Click( object sender, EventArgs e )
        {
            AddORMExtendedProperties( Scope.DatabaseScope );
        }
        
        #endregion

        #region TreeView events
        private void DbView_Click( object sender, EventArgs e )
        {

        }
        private void DbView_NodeMouseClick( object sender, TreeNodeMouseClickEventArgs e )
        {
            try
            {
                
                //Get object data by node type.
                DbTree.SelectedNode = e.Node;
                if( e.Node.Tag != null )
                {
                    Hashtable TagValues = (Hashtable)e.Node.Tag;
                    switch( TagValues["Type"].ToString( ) )
                    {
                        case NODETYPE_DB:
                            SetCurrentObject( e.Node, NODETYPE_DB);
                            GetDatabaseDescription( e.Node );
                            break;
                        case NODETYPE_TABLE:
                            SetCurrentObject( e.Node, NODETYPE_TABLE );
                            GetTableDescription( e.Node );
                            break;
                        case NODETYPE_COLUMN:
                            SetCurrentObject( e.Node, NODETYPE_COLUMN );
                            GetColumnDescription( e.Node );
                            break;
                        case NODETYPE_FK:
                            break;
                        case NODETYPE_IX:
                            break;
                        case NODETYPE_PROP:
                            break;
                        case NODETYPE_XPROP:
                            break;
                        default:
                            break;
                    }
                }
                
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void DbView_KeyUp( object sender, KeyEventArgs e )
        {
            try
            {
                if( DbTree.SelectedNode != null )
                {
                    //Get object data by node type.
                    TreeNode CurrentNode = DbTree.SelectedNode;
                    if( DbTree.SelectedNode.Tag != null )
                    {
                        Hashtable TagValues = (Hashtable)CurrentNode.Tag;
                        switch( TagValues["Type"].ToString( ) )
                        {
                            case NODETYPE_DB:
                                SetCurrentObject( CurrentNode, NODETYPE_DB );
                                GetDatabaseDescription( CurrentNode );
                                break;
                            case NODETYPE_TABLE:
                                SetCurrentObject( CurrentNode, NODETYPE_TABLE );
                                GetTableDescription( CurrentNode );
                                break;
                            case NODETYPE_COLUMN:
                                SetCurrentObject( CurrentNode, NODETYPE_COLUMN );
                                GetColumnDescription( CurrentNode );
                                break;
                            case NODETYPE_FK:
                                break;
                            case NODETYPE_IX:
                                break;
                            case NODETYPE_PROP:
                                break;
                            case NODETYPE_XPROP:
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void DbView_KeyDown( object sender, KeyEventArgs e )
        {
            try
            {
                if( DbTree.SelectedNode != null )
                {
                    //Get object data by node type.
                    TreeNode CurrentNode = DbTree.SelectedNode;
                    if( DbTree.SelectedNode.Tag != null )
                    {
                        Hashtable TagValues = (Hashtable)CurrentNode.Tag;
                        switch( TagValues["Type"].ToString( ) )
                        {
                            case NODETYPE_DB:
                                SetCurrentObject( CurrentNode, NODETYPE_DB );
                                GetDatabaseDescription( CurrentNode );
                                break;
                            case NODETYPE_TABLE:
                                SetCurrentObject( CurrentNode, NODETYPE_TABLE );
                                GetTableDescription( CurrentNode );
                                break;
                            case NODETYPE_COLUMN:
                                SetCurrentObject( CurrentNode, NODETYPE_COLUMN );
                                GetColumnDescription( CurrentNode );
                                break;
                            case NODETYPE_FK:
                                break;
                            case NODETYPE_IX:
                                break;
                            case NODETYPE_PROP:
                                break;
                            case NODETYPE_XPROP:
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void DbView_AfterSelect( object sender, TreeViewEventArgs e )
        {

        }
        private void DbTree_BeforeExpand( object sender, TreeViewCancelEventArgs e )
        {
            try
            {

                //Get object data by node type.
                DbTree.SelectedNode = e.Node;
                if( e.Node.Tag != null )
                {
                    Hashtable TagValues = (Hashtable)e.Node.Tag;
                    switch( TagValues["Type"].ToString( ) )
                    {
                        case NODETYPE_DB:
                            break;
                        case NODETYPE_TABLE:
                            //Add column nodes.
                            PopulateColumns( e.Node, true );
                            break;
                        case NODETYPE_COLUMN:
                            break;
                        case NODETYPE_FK:
                            break;
                        case NODETYPE_IX:
                            break;
                        case NODETYPE_PROP:
                            break;
                        case NODETYPE_XPROP:
                            break;
                        default:
                            break;
                    }
                }

            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }
        private void DbTree_AfterExpand( object sender, TreeViewEventArgs e )
        {

        }
        private void DbTree_AfterSelect( object sender, TreeViewEventArgs e )
        {

        }
        private void DbTree_AfterCheck( object sender, TreeViewEventArgs e )
        {
            try
            {

                if( e.Node.Tag != null )
                {
                    Hashtable TagValues = (Hashtable)e.Node.Tag;
                    switch( TagValues["Type"].ToString( ) )
                    {
                        case NODETYPE_DB:
                            foreach( TreeNode node in e.Node.Nodes )
                            {
                                node.Checked = e.Node.Checked;
                            }
                            break;
                        case NODETYPE_TABLE:
                            
                            break;
                        case NODETYPE_COLUMN:
                            
                            break;
                        case NODETYPE_FK:
                            break;
                        case NODETYPE_IX:
                            break;
                        case NODETYPE_PROP:
                            break;
                        case NODETYPE_XPROP:
                            break;
                        default:
                            break;
                    }
                }

            }
            catch( Exception ex ) { MessageBox.Show( ex.Message ); }
        }

        #endregion

        #region Buttons events
        private void bAddProperty_Click( object sender, EventArgs e )
        {
            AddSingleExtendedProperty( _currentObject, _currentObjectType );
        }
        private void bRemoveProperty_Click( object sender, EventArgs e )
        {
            if( MessageBox.Show( "Are you sure to remove this property?.", "Remove confirmation", MessageBoxButtons.YesNo ) == DialogResult.Yes )
            {
                
            }
        }
        private void bSaveObjectDescription_Click( object sender, EventArgs e )
        {
            TreeNode CurrentNode = DbTree.SelectedNode;
            Hashtable TagValues = (Hashtable)CurrentNode.Tag;
            switch( TagValues["Type"].ToString( ) )
            {
                case NODETYPE_DB:
                    SaveObjectDescription( _currentDatabase, NODETYPE_DB );
                    break;
                case NODETYPE_TABLE:
                    SaveObjectDescription( _currentTable, NODETYPE_TABLE);
                    break;
                case NODETYPE_COLUMN:
                    SaveObjectDescription( _currentColumn, NODETYPE_COLUMN);
                    break;
                case NODETYPE_FK:
                    break;
                case NODETYPE_IX:
                    break;
                case NODETYPE_PROP:
                    break;
                case NODETYPE_XPROP:
                    break;
                default:
                    break;
            }
            
        }   
        #endregion

        #region Others events
        private void ComboDatabases_TextChanged( object sender, EventArgs e )
        {
            PopulateTables( false );
        }  
        private void fTableDesc_Leave( object sender, EventArgs e )
        {
            //Save description value depend on settings
            if( ConfigValues.SaveOnLostFocus )
            {
                if( DbTree.SelectedNode != null )
                {
                    //Get object data by node type.
                    TreeNode CurrentNode = DbTree.SelectedNode;
                    if( DbTree.SelectedNode.Tag != null )
                    {
                        Hashtable TagValues = (Hashtable)CurrentNode.Tag;
                        switch( TagValues["Type"].ToString( ) )
                        {
                            case NODETYPE_DB:
                                SaveObjectDescription( _currentDatabase, NODETYPE_DB );
                                break;
                            case NODETYPE_TABLE:
                                SaveObjectDescription( _currentTable, NODETYPE_TABLE );
                                break;
                            case NODETYPE_COLUMN:
                                SaveObjectDescription( _currentColumn, NODETYPE_COLUMN );
                                break;
                            case NODETYPE_FK:
                                break;
                            case NODETYPE_IX:
                                break;
                            case NODETYPE_PROP:
                                break;
                            case NODETYPE_XPROP:
                                break;
                            default:
                                break;
                        }
                    }
                }
            }

        }
        #endregion   

        #region ToolStrip events
        private void ServersList_TextChanged( object sender, EventArgs e )
        {

        }
        private void ServersList_SelectedIndexChanged( object sender, EventArgs e )
        {
            //On change server update the current conectionstring.
            
            _currentServerConnectionString = GetServerConnectionString( ServersList.SelectedItem.ToString( ) );
        }
        #endregion
        
        #region PropertiesDatagrid events
        private void DbProperties_CellBeginEdit( object sender, DataGridViewCellCancelEventArgs e )
        {
            _propertyOldName = DbProperties.Rows[e.RowIndex].Cells[0].Value.ToString( );
            if( _propertyOldName == ConfigValues.DescriptionLabel ) 
            {
                DbProperties.EndEdit( );
            }
            
        }
        private void DbProperties_CellEndEdit( object sender, DataGridViewCellEventArgs e )
        {
            
            //Name is the first columns index 0
            var Name = DbProperties.Rows[e.RowIndex].Cells[0].Value.ToString( );
            var Value = DbProperties.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString( );
            if( e.ColumnIndex == 0 )
            {
                //Update property name, only update if not is description property.
                if( !( _propertyOldName == ConfigValues.DescriptionLabel ) )
                {
                    UpdateProperty( _currentObject, _currentObjectType, _propertyOldName, Value, true );
                }         
            }
            else
            {
                //Update the property value.
                UpdateProperty( _currentObject, _currentObjectType, Name, Value, false );
            }
            PopulateExtendedProperties( _currentPropertiesCollection );
        }
        private void DbProperties_UserDeletedRow( object sender, DataGridViewRowEventArgs e )
        {
            var Name = e.Row.Cells[0].Value.ToString( );
            RemoveProperty( _currentObject, _currentObjectType, Name );
        }
        private void DbProperties_CellContentDoubleClick( object sender, DataGridViewCellEventArgs e )
        {
            
        }
        private void DbProperties_CellMouseDoubleClick( object sender, DataGridViewCellMouseEventArgs e )
        {
            if( e.ColumnIndex > 0 )
            {
                EditText EditTextForm = new EditText( );
                EditTextForm.SetText( DbProperties.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString( ) );
                if( EditTextForm.ShowDialog( ) == DialogResult.OK )
                {
                    DbProperties.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = EditTextForm.EditedText;
                }
                EditTextForm.Dispose( );
            }
        }
        #endregion 

        

        #endregion

        

    }
    internal static class ConfigValues
    {
        internal static string DescriptionLabel { get; set; }
        internal static bool SaveOnLostFocus { get; set; }
        internal static bool ViewSystemDatabases { get; set; }
        internal static bool ViewSystemTables{ get; set; }
        internal static bool OverrideProperties { get; set; }
    }
    internal enum Scope
    {
        DatabaseScope, TableScope, SelectedScope
    }
}
